記我的第一次面試總結——閉包和原型鏈
廢話先說
最近投了數多簡歷,大都了無音訊,昨天有幸收到了新蛋集團的面試電話,在今天上午進行了電話面試,面試的小哥十分和藹,聲音聽起來很舒服,也特別有耐心,可惜自己回答的並不好,結果就順其自然吧。
但是通過這次面試,我對自己的瞭解加深了不少,一是自己除了前端基礎的知識之外,對於網路協議及演算法方面的知識瞭解太少,二是對於自己知道的知識無法準確描述。
在這先整理下自己這次面試的問題,並打算對自己的不足之處進行鞏固加強,不要再錯過本可以抓住的機會了。
正文開始
問題一:簡單介紹一下閉包
1.概念:閉包就是有權訪另一個函式作用域中變數的函式。 如:
function a (){
var m=3 ;
function b(){
console.log(m);
console.log('string');
};
return b;
}
var result=a();
result(); //3 'string'
上面的函式a和b就構成了一個閉包。在全域性中執行函式b中可以引用a中的變數m。
2.特性:
- 函式巢狀函式;
- 函式內部可以引用函式外部的引數和變數;
- 函式變數和引數不會被垃圾回收機制回收;
3.優缺點:
優點
- 希望一個變數長期駐紮在記憶體中
- 避免全域性變數的汙染
- 私有成員的存在
缺點
- 常駐記憶體,增大記憶體使用量,使用不當回造成記憶體洩漏;
4.自執行函式的好處
- 隔離作用域,避免全域性作用域汙染
- 模擬塊級作用域
問題二:判斷下面函式是不是閉包,有什麼問題嗎?
function a(){
var m=3;
function b(){
console.log(m);
};
function c(){
console.log('string');
};
return b;
}
var result=a();
result();
它是一個閉包,但是閉包是b而不是c,因為只是返回了b.
問題三:描述一下原型鏈
1.原型:
每個函式都會預設有一個prototype屬性,它是一個指標,指向此函式的原型物件。而建構函式作為一個函式,同樣擁有自己的原型物件,而通過建構函式生成的物件例項中,擁有一個_proto_ 屬性,它指向建構函式的原型物件,我們把建構函式的原型物件稱為物件例項的原型。
如圖:person就是建構函式,而Person prototype原型物件,也是物件例項person1的原型,此例項會繼承所有存在它原型中的所有屬性及方法。
原型鏈
既然每個例項物件都有一個原型,而每個建構函式也都能建立例項,那假如我們將建構函式 f1 的原型屬性指向建構函式f2的例項物件,那麼建構函式f1的例項物件就能訪問f2的原型屬性,依次類推,我們還可以把建構函式f3的原型屬性指向f2的隊例項物件,那麼f3的例項物件同樣可以訪問到f1的原型,這樣,就構成了一條原型鏈。
如圖:從上到下依次講解,首先,原型鏈的頂端是Object prototype
,它的_proto_ 屬性為 ,接下來看建構函式SuperType
,它的prototype屬性指向的是原型物件SuperType prototype
,這個原型物件其實是Object的一個例項物件,因為它的_proto_ 屬性指向Object prototype
,因此,SuperType
的例項屬性可以訪問Object prototype
中的屬性與方法。
同理,我們通過SubType.prototype=new SuperType()
,可以將subType的原型物件指向為SuperType的一個例項物件,這樣SubType 的例項物件instance通過原型鏈可以訪問到上面三個原型中的合法屬性與方法。
問題四:關於setTimeout()
首先關於setTimeout()我的理解為:
JavaScript引擎是單執行緒執行的,瀏覽器無論在什麼時候都只且只有一個執行緒在執行JavaScript程式。
意思就是隻要是setTimeout中的程式碼,執行時間總是要等到其他執行緒結束後才執行。
題目:
setTimeout(console.log('a'),0)
console.log('c');
的輸出順序;
我答的是先輸出c後輸出a,時候在瀏覽器裡執行發現並不是按照我想的那樣,結果是按順序輸出的。後來又試了其他情況才發現自己以前的理解有偏差。
setTimeout(a,0);
console.log('b');
function a(){
console.log('a')
}
//此時輸出順序為 b, a;
setTimeout(a(),0);
console.log('b');
function a(){
console.log('a')
};
//此時輸出順序為 a,b;
這樣下來就發現題目中的寫法其實並沒有用到setTiemout()的知識,當程式執行到它時他會立刻給出結果而不需要等待。另外,這樣一來setTimeout也就沒有作用了,在實際開發中這種寫法是不正確的。