1. 程式人生 > >2018最新Web前端經典面試試題及答案

2018最新Web前端經典面試試題及答案

本篇收錄了一些面試中經常會遇到的經典面試題以及自己面試過程中遇到的一些問題,並且都給出了我在網上收集的答案。馬上就要過春節了,開年就是嶄新的一年,相信很多的前端開發者會有一些跳槽的悸動,通過對本篇知識的整理以及經驗的總結,希望能幫到更多的前端面試者。(如有錯誤或更好的答案,歡迎指正,水平有限,望各位不吝指教。:)

javascript:

 JavaScript中如何檢測一個變數是一個String型別?請寫出函式實現

typeof(obj) === "string"
typeof obj === "string"
obj.constructor === String

請用js去除字串空格?

方法一:使用replace正則匹配的方法

去除所有空格: str = str.replace(/\s*/g,"");      

去除兩頭空格: str = str.replace(/^\s*|\s*$/g,"");

去除左空格: str = str.replace( /^\s*/, “”);

去除右空格: str = str.replace(/(\s*$)/g, "");

str為要去除空格的字串,例項如下:

var str = " 23 23 ";
var str2 = str.replace(/\s*/g,"");
console.log(str2); // 2323

方法二:使用str.trim()方法

str.trim()侷限性:無法去除中間的空格,例項如下:

var str = "   xiao  ming   ";
var str2 = str.trim();
console.log(str2);   //xiao  ming 

同理,str.trimLeft(),str.trimRight()分別用於去除字串左右空格。

方法三:使用jquery,$.trim(str)方法

$.trim(str)侷限性:無法去除中間的空格,例項如下:

var str = "   xiao  ming   ";
var str2 = $.trim(str)
console.log(str2);   
// xiao ming
function showWindowHref(){
    var sHref = window.location.href;
    var args = sHref.split('?');
    if(args[0] == sHref){
        return "";
    }
    var arr = args[1].split('&');
    var obj = {};
    for(var i = 0;i< arr.length;i++){
        var arg = arr[i].split('=');
        obj[arg[0]] = arg[1];
    }
    return obj;
}
var href = showWindowHref(); // obj
console.log(href['name']); // xiaoming

js 字串操作函式

  我這裡只是列舉了常用的字串函式,具體使用方法,請參考網址

  • concat() – 將兩個或多個字元的文字組合起來,返回一個新的字串。

  • indexOf() – 返回字串中一個子串第一處出現的索引。如果沒有匹配項,返回 -1 。

  • charAt() – 返回指定位置的字元。

  • lastIndexOf() – 返回字串中一個子串最後一處出現的索引,如果沒有匹配項,返回 -1 。

  • match() – 檢查一個字串是否匹配一個正則表示式。

  • substr() 函式 -- 返回從string的startPos位置,長度為length的字串

  • substring() – 返回字串的一個子串。傳入引數是起始位置和結束位置。

  • slice() – 提取字串的一部分,並返回一個新字串。

  • replace() – 用來查詢匹配一個正則表示式的字串,然後使用新字串代替匹配的字串。

  • search() – 執行一個正則表示式匹配查詢。如果查詢成功,返回字串中匹配的索引值。否則返回 -1 。

  • split() – 通過將字串劃分成子串,將一個字串做成一個字串陣列。

  • length – 返回字串的長度,所謂字串的長度是指其包含的字元的個數。

  • toLowerCase() – 將整個字串轉成小寫字母。

  • toUpperCase() – 將整個字串轉成大寫字母。

怎樣新增、移除、移動、複製、建立和查詢節點?

 1)建立新節點

  createDocumentFragment() //建立一個DOM片段
  createElement() //建立一個具體的元素
  createTextNode() //建立一個文字節點

2)新增、移除、替換、插入
  appendChild() //新增
  removeChild() //移除
  replaceChild() //替換
  insertBefore() //插入

3)查詢
  getElementsByTagName() //通過標籤名稱
  getElementsByName() //通過元素的Name屬性的值
  getElementById() //通過元素Id,唯一性

寫出3個使用this的典型應用

(1)、在html元素事件屬性中使用,如:

<input type=”button” onclick=”showInfo(this);” value=”點選一下”/>

(2)、建構函式

function Animal(name, color) {
  this.name = name;
  this.color = color;
}

(3)、input點選,獲取值

<input type="button" id="text" value="點選一下" />
<script type="text/javascript">
    var btn = document.getElementById("text");
    btn.onclick = function() {
        alert(this.value);    //此處的this是按鈕元素
    }
</script>

(4)、apply()/call()求陣列最值

var  numbers = [5, 458 , 120 , -215 ]; 
var  maxInNumbers = Math.max.apply(this, numbers);  
console.log(maxInNumbers);  // 458
var maxInNumbers = Math.max.call(this,5, 458 , 120 , -215); 
console.log(maxInNumbers);  // 458

比較typeof與instanceof?

相同點:JavaScript 中 typeof 和 instanceof 常用來判斷一個變數是否為空,或者是什麼型別的。

typeof的定義和用法:返回值是一個字串,用來說明變數的資料型別。

細節:

(1)、typeof 一般只能返回如下幾個結果:number,boolean,string,function,object,undefined。

(2)、typeof 來獲取一個變數是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因為如果 a 不存在(未宣告)則會出錯。

(3)、對於 Array,Null 等特殊物件使用 typeof 一律返回 object,這正是 typeof 的侷限性。

Instanceof定義和用法:instanceof 用於判斷一個變數是否屬於某個物件的例項。

例項演示:

a instanceof b?alert("true"):alert("false"); //a是b的例項?真:假

var a = new Array(); 
alert(a instanceof Array);  // true
alert(a instanceof Object)  // true

如上,會返回 true,同時 alert(a instanceof Object) 也會返回 true;這是因為 Array 是 object 的子類。

function test(){};
var a = new test();
alert(a instanceof test)   // true

細節:

(1)、如下,得到的結果為‘N’,這裡的 instanceof 測試的 object 是指 js 語法中的 object,不是指 dom 模型物件。

if (window instanceof Object){ alert('Y')} else {  alert('N');}  // 'N'

 如何理解閉包?

1、定義和用法:當一個函式的返回值是另外一個函式,而返回的那個函式如果呼叫了其父函式內部的其它變數,如果返回的這個函式在外部被執行,就產生了閉包。

2、表現形式:使函式外部能夠呼叫函式內部定義的變數。

3、例項如下:

(1)、根據作用域鏈的規則,底層作用域沒有宣告的變數,會向上一級找,找到就返回,沒找到就一直找,直到window的變數,沒有就返回undefined。這裡明顯count 是函式內部的flag2 的那個count 。

var count=10;   //全域性作用域 標記為flag1
function add(){
    var count=0;    //函式全域性作用域 標記為flag2
    return function(){
        count+=1;   //函式的內部作用域
        alert(count);
    }
}
var s = add()
s();//輸出1
s();//輸出2

4、變數的作用域

要理解閉包,首先必須理解Javascript特殊的變數作用域。

變數的作用域分類:全域性變數和區域性變數。

特點:

1、函式內部可以讀取函式外部的全域性變數;在函式外部無法讀取函式內的區域性變數。

2、函式內部宣告變數的時候,一定要使用var命令。如果不用的話,你實際上聲明瞭一個全域性變數!

 5、使用閉包的注意點

1)濫用閉包,會造成記憶體洩漏:由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除。

2)會改變父函式內部變數的值。所以,如果你把父函式當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函式內部變數的值。

 什麼是跨域?跨域請求資源的方法有哪些?

1、什麼是跨域?

由於瀏覽器同源策略,凡是傳送請求url的協議、域名、埠三者之間任意一與當前頁面地址不同即為跨域。存在跨域的情況:

  • 網路協議不同,如http協議訪問https協議。

  • 埠不同,如80埠訪問8080埠。

  • 域名不同,如qianduanblog.com訪問baidu.com。

  • 子域名不同,如abc.qianduanblog.com訪問def.qianduanblog.com。

  • 域名和域名對應ip,如www.a.com訪問20.205.28.90.

2、跨域請求資源的方法:

(1)、porxy代理

定義和用法:proxy代理用於將請求傳送給後臺伺服器,通過伺服器來發送請求,然後將請求的結果傳遞給前端。

實現方法:通過nginx代理;

注意點:1、如果你代理的是https協議的請求,那麼你的proxy首先需要信任該證書(尤其是自定義證書)或者忽略證書檢查,否則你的請求無法成功。

(2)、CORS 【Cross-Origin Resource Sharing】

定義和用法:是現代瀏覽器支援跨域資源請求的一種最常用的方式。

使用方法:一般需要後端人員在處理請求資料的時候,新增允許跨域的相關操作。如下:

res.writeHead(200, {
    "Content-Type": "text/html; charset=UTF-8",
    "Access-Control-Allow-Origin":'http://localhost',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
    'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'
});

(3)、jsonp

定義和用法:通過動態插入一個script標籤。瀏覽器對script的資源引用沒有同源限制,同時資源載入到頁面後會立即執行(沒有阻塞的情況下)。

特點:通過情況下,通過動態建立script來讀取他域的動態資源,獲取的資料一般為json格式。

例項如下:

<script>
    function testjsonp(data) {
       console.log(data.name); // 獲取返回的結果
    }
</script>
<script>
    var _script = document.createElement('script');
    _script.type = "text/javascript";
    _script.src = "http://localhost:8888/jsonp?callback=testjsonp";
    document.head.appendChild(_script);
</script>

缺點:

  1、這種方式無法傳送post請求(這裡)

  2、另外要確定jsonp的請求是否失敗並不容易,大多數框架的實現都是結合超時時間來判定。

談談垃圾回收機制方式及記憶體管理

回收機制方式

1、定義和用法:垃圾回收機制(GC:Garbage Collection),執行環境負責管理程式碼執行過程中使用的記憶體。

2、原理:垃圾收集器會定期(週期性)找出那些不在繼續使用的變數,然後釋放其記憶體。但是這個過程不是實時的,因為其開銷比較大,所以垃圾回收器會按照固定的時間間隔週期性的執行。

3、例項如下:

function fn1() {
    var obj = {name: 'hanzichi', age: 10};
}
function fn2() {
    var obj = {name:'hanzichi', age: 10};
   return obj;
}
var a = fn1();
var b = fn2();

fn1中定義的obj為區域性變數,而當呼叫結束後,出了fn1的環境,那麼該塊記憶體會被js引擎中的垃圾回收器自動釋放;在fn2被呼叫的過程中,返回的物件被全域性變數b所指向,所以該塊記憶體並不會被釋放。

 4、垃圾回收策略:標記清除(較為常用)和引用計數。

標記清除:

  定義和用法:當變數進入環境時,將變數標記"進入環境",當變數離開環境時,標記為:"離開環境"。某一個時刻,垃圾回收器會過濾掉環境中的變數,以及被環境變數引用的變數,剩下的就是被視為準備回收的變數。

  到目前為止,IE、Firefox、Opera、Chrome、Safari的js實現使用的都是標記清除的垃圾回收策略或類似的策略,只不過垃圾收集的時間間隔互不相同。

引用計數:

  定義和用法:引用計數是跟蹤記錄每個值被引用的次數。

  基本原理:就是變數的引用次數,被引用一次則加1,當這個引用計數為0時,被視為準備回收的物件。

 記憶體管理

1、什麼時候觸發垃圾回收?

垃圾回收器週期性執行,如果分配的記憶體非常多,那麼回收工作也會很艱鉅,確定垃圾回收時間間隔就變成了一個值得思考的問題。

IE6的垃圾回收是根據記憶體分配量執行的,當環境中的變數,物件,字串達到一定數量時觸發垃圾回收。垃圾回收器一直處於工作狀態,嚴重影響瀏覽器效能。

IE7中,垃圾回收器會根據記憶體分配量與程式佔用記憶體的比例進行動態調整,開始回收工作。

2、合理的GC方案:(1)、遍歷所有可訪問的物件; (2)、回收已不可訪問的物件。

3、GC缺陷:(1)、停止響應其他操作;

4、GC優化策略:(1)、分代回收(Generation GC);(2)、增量GC

開發過程中遇到的記憶體洩露情況,如何解決的?

1、定義和用法:

記憶體洩露是指一塊被分配的記憶體既不能使用,又不能回收,直到瀏覽器程序結束。C#和Java等語言採用了自動垃圾回收方法管理記憶體,幾乎不會發生記憶體洩露。我們知道,瀏覽器中也是採用自動垃圾回收方法管理記憶體,但由於瀏覽器垃圾回收方法有bug,會產生記憶體洩露。

2、記憶體洩露的幾種情況:

(1)、當頁面中元素被移除或替換時,若元素繫結的事件仍沒被移除,在IE中不會作出恰當處理,此時要先手工移除事件,不然會存在記憶體洩露。

例項如下:

<div id="myDiv">
    <input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        document.getElementById("myDiv").innerHTML = "Processing...";
    }
</script>

解決方法如下:

<div id="myDiv">
    <input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
    btn.onclick = null;
        document.getElementById("myDiv").innerHTML = "Processing...";
    }
</script>
(2)、由於是函式內定義函式,並且內部函式--事件回撥的引用外暴了,形成了閉包。閉包可以維持函式內區域性變數,使其得不到釋放。 例項如下:
function bindEvent(){
    var obj=document.createElement("XXX");
    obj.onclick=function(){
        //Even if it's a empty function
    }
}

解決方法如下:

function bindEvent(){
    var obj=document.createElement("XXX");
    obj.onclick=function(){
         //Even if it's a empty function
    }
    obj=null;
}

 javascript面向物件中繼承實現?

面向物件的基本特徵有:封閉、繼承、多型。

在JavaScript中實現繼承的方法:

1. 原型鏈(prototype chaining)

2. call()/apply()

3. 混合方式(prototype和call()/apply()結合)

4. 物件冒充

繼承的方法如下:

1、prototype原型鏈方式:

function teacher(name){
    this.name = name;
}
teacher.prototype.sayName = function(){
    console.log("name is "+this.name);
}
var teacher1 = new teacher("xiaoming");
teacher1.sayName();

function student(name){
    this.name = name;
}
student.prototype = new teacher()
var student1 = new student("xiaolan");
student1.sayName();
//  name is xiaoming
//  name is xiaolan
2、call()/apply()方法 function teacher(name,age){ this.name = name; this.age = age; this.sayhi = function(){ alert('name:'+name+", age:"+age); } } function student(){ var args = arguments; teacher.call(this,args[0],args[1]); // teacher.apply(this,arguments); } var teacher1 = new teacher('xiaoming',23); teacher1.sayhi(); var student1 = new student('xiaolan',12); student1.sayhi(); // alert: name:xiaoming, age:23 // alert: name:xiaolan, age:12
3、混合方法【prototype,call/apply】 function teacher(name,age){ this.name = name; this.age = age; } teacher.prototype.sayName = function(){ console.log('name:'+this.name); } teacher.prototype.sayAge = function(){ console.log('age:'+this.age); } function student(){ var args = arguments; teacher.call(this,args[0],args[1]); } student.prototype = new teacher(); var student1 = new student('xiaolin',23); student1.sayName(); student1.sayAge(); // name:xiaolin // age:23 4、物件冒充 function Person(name,age){ this.name = name; this.age = age; this.show = function(){ console.log(this.name+", "+this.age); } } function Student(name,age){ this.student = Person; //將Person類的建構函式賦值給this.student this.student(name,age); //js中實際上是通過物件冒充來實現繼承的 delete this.student; //移除對Person的引用 } var s = new Student("小明",17); s.show(); var p = new Person("小花",18); p.show(); // 小明, 17 // 小花, 18

javascript相關程式計算題

1、判斷一個字串中出現次數最多的字元,統計這個次數

var str = 'asdfssaaasasasasaa';
var json = {};
for (var i = 0; i < str.length; i++) {
    if(!json[str.charAt(i)]){
       json[str.charAt(i)] = 1;
    }else{
       json[str.charAt(i)]++;
    }
};
var iMax = 0;
var iIndex = '';
for(var i in json){
    if(json[i]>iMax){
         iMax = json[i];
         iIndex = i;
    }
}        
console.log('出現次數最多的是:'+iIndex+'出現'+iMax+'次');

結果如下:出現次數最多的是:a出現9次

JavaScript 陣列(Array)物件

1、Array相關的屬性和方法

這裡只是做了相關的列舉,具體的使用方法,請參考網址

Array 物件屬性

constructor 返回對建立此物件的陣列函式的引用。

length 設定或返回陣列中元素的數目。

prototype 使您有能力向物件新增屬性和方法。

Array 物件方法

concat() 連線兩個或更多的陣列,並返回結果。

join() 把陣列的所有元素放入一個字串。元素通過指定的分隔符進行分隔。

pop() 刪除並返回陣列的最後一個元素。  

shift() 刪除並返回陣列的第一個元素

push() 向陣列的末尾新增一個或更多元素,並返回新的長度。

unshift() 向陣列的開頭新增一個或更多元素,並返回新的長度。

reverse() 顛倒陣列中元素的順序。

slice() 從某個已有的陣列返回選定的元素

sort() 對陣列的元素進行排序

splice() 刪除元素,並向陣列新增新元素。

toSource() 返回該物件的原始碼。

toString() 把陣列轉換為字串,並返回結果。

toLocaleString() 把陣列轉換為本地陣列,並返回結果。

valueOf() 返回陣列物件的原始值

2、編寫一個方法 去掉一個數組的重複元素

方法一:

var arr = [0,2,3,4,4,0,2];
var obj = {};
var tmp = [];
for(var i = 0 ;i< arr.length;i++){
   if( !obj[arr[i]] ){
      obj[arr[i]] = 1;
      tmp.push(arr[i]);
   }
}
console.log(tmp);

結果如下: [0, 2, 3, 4]

 方法二:

var arr = [2,3,4,4,5,2,3,6],
   arr2 = [];
for(var i = 0;i< arr.length;i++){
    if(arr2.indexOf(arr[i]) < 0){
        arr2.push(arr[i]);
    }
}
console.log(arr2);

結果為:[2, 3, 4, 5, 6]

 方法三:

var arr = [2,3,4,4,5,2,3,6];
var arr2 = arr.filter(function(element,index,self){
return self.indexOf(element) === index;
});
console.log(arr2);

結果為:[2, 3, 4, 5, 6]

回到頂部

 jquery相關

1、 jQuery 庫中的 $() 是什麼?

  $() 函式是 jQuery() 函式的別稱。$() 函式用於將任何物件包裹成 jQuery 物件,接著你就被允許呼叫定義在 jQuery 物件上的多個不同方法。你可以將一個選擇器字串傳入 $() 函式,它會返回一個包含所有匹配的 DOM 元素陣列的 jQuery 物件。

2、如何找到所有 HTML select 標籤的選中項?

$('[name=selectname] :selected')

3、$(this) 和 this 關鍵字在 jQuery 中有何不同?

$(this) 返回一個 jQuery 物件,你可以對它呼叫多個 jQuery 方法,比如用 text() 獲取文字,用val() 獲取值等等。

而 this 代表當前元素,它是 JavaScript 關鍵詞中的一個,表示上下文中的當前 DOM 元素。你不能對它呼叫 jQuery 方法,直到它被 $() 函式包裹,例如 $(this)。

4、jquery怎麼移除標籤onclick屬性?

獲得a標籤的onclick屬性: $("a").attr("onclick")

刪除onclick屬性:$("a").removeAttr("onclick");

設定onclick屬性:$("a").attr("onclick","test();");

5、jquery中addClass,removeClass,toggleClass的使用。

$(selector).addClass(class):為每個匹配的元素新增指定的類名

$(selector).removeClass(class):從所有匹配的元素中刪除全部或者指定的類,刪除class中某個值;

$(selector).toggleClass(class):如果存在(不存在)就刪除(新增)一個類

$(selector).removeAttr(class);刪除class這個屬性;

6、JQuery有幾種選擇器?

(1)、基本選擇器:#id,class,element,*;

(2)、層次選擇器:parent > child,prev + next ,prev ~ siblings

(3)、基本過濾器選擇器::first,:last ,:not ,:even ,:odd ,:eq ,:gt ,:lt

(4)、內容過濾器選擇器: :contains ,:empty ,:has ,:parent

(5)、可見性過濾器選擇器::hidden ,:visible

(6)、屬性過濾器選擇器:[attribute] ,[attribute=value] ,[attribute!=value] ,[attribute^=value] ,[attribute$=value] ,[attribute*=value]

(7)、子元素過濾器選擇器::nth-child ,:first-child ,:last-child ,:only-child

(8)、表單選擇器: :input ,:text ,:password ,:radio ,:checkbox ,:submit 等;

(9)、表單過濾器選擇器::enabled ,:disabled ,:checked ,:selected

7、jQuery中的Delegate()函式有什麼作用?

   delegate()會在以下兩個情況下使用到:

 1、如果你有一個父元素,需要給其下的子元素新增事件,這時你可以使用delegate()了,程式碼如下:

$("ul").delegate("li", "click", function(){ $(this).hide(); });

 2、當元素在當前頁面中不可用時,可以使用delegate()

8、$(document).ready()方法和window.onload有什麼區別?

 (1)、window.onload方法是在網頁中所有的元素(包括元素的所有關聯檔案)完全載入到瀏覽器後才執行的。

 (2)、$(document).ready() 方法可以在DOM載入就緒時就對其進行操縱,並呼叫執行繫結的函式。

9、如何用jQuery禁用瀏覽器的前進後退按鈕?

實現程式碼如下:

<script type="text/javascript" language="javascript">
  $(document).ready(function() {
    window.history.forward(1);
      //OR window.history.forward(-1);
  });
</script>

10、 jquery中$.get()提交和$.post()提交有區別嗎?

相同點:都是非同步請求的方式來獲取服務端的資料;

異同點:

1、請求方式不同:$.get() 方法使用GET方法來進行非同步請求的。$.post() 方法使用POST方法來進行非同步請求的。

2、引數傳遞方式不同:get請求會將引數跟在URL後進行傳遞,而POST請求則是作為HTTP訊息的實體內容傳送給Web伺服器的,這種傳遞是對使用者不可見的。

3、資料傳輸大小不同:get方式傳輸的資料大小不能超過2KB 而POST要大的多

4、安全問題: GET 方式請求的資料會被瀏覽器快取起來,因此有安全問題。

11、寫出一個簡單的$.ajax()的請求方式?

$.ajax({
    url:'http://www.baidu.com',
    type:'POST',
    data:data,
    cache:true,
    headers:{},
    beforeSend:function(){},
    success:function(){},
    error:function(){},
    complete:function(){}
}); 

12、jQuery的事件委託方法bind 、live、delegate、on之間有什麼區別?

(1)、bind 【jQuery 1.3之前】

定義和用法:主要用於給選擇到的元素上繫結特定事件型別的監聽函式;

語法:bind(type,[data],function(eventObject));

特點:

  (1)、適用於頁面元素靜態繫結。只能給呼叫它的時候已經存在的元素繫結事件,不能給未來新增的元素繫結事件。

  (2)、當頁面載入完的時候,你才可以進行bind(),所以可能產生效率問題。

例項如下:$( "#members li a" ).bind( "click", function( e ) {} );

(2)、live 【jQuery 1.3之後】

定義和用法:主要用於給選擇到的元素上繫結特定事件