1. 程式人生 > >記我的第一次面試總結——閉包和原型鏈

記我的第一次面試總結——閉包和原型鏈

廢話先說

最近投了數多簡歷,大都了無音訊,昨天有幸收到了新蛋集團的面試電話,在今天上午進行了電話面試,面試的小哥十分和藹,聲音聽起來很舒服,也特別有耐心,可惜自己回答的並不好,結果就順其自然吧。

但是通過這次面試,我對自己的瞭解加深了不少,一是自己除了前端基礎的知識之外,對於網路協議及演算法方面的知識瞭解太少,二是對於自己知道的知識無法準確描述。

在這先整理下自己這次面試的問題,並打算對自己的不足之處進行鞏固加強,不要再錯過本可以抓住的機會了。

正文開始

問題一:簡單介紹一下閉包

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也就沒有作用了,在實際開發中這種寫法是不正確的。