new new Foo().getName() 一道前端面試題引發的思考


今天想着鄰近畢業季,估計又會有很多稀奇古怪的面試題,看掘金社區的時候看到一道賊有意思的題,一開始看的十分懵逼,后來捋了捋,將心得總結一下。

function Foo() {
    getName = function () {
        console.log(1);
    }
    return this;
}

Foo.getName = function () {
    console.log(2);
}

Foo.prototype.getName = function () {
    console.log(3);
}

var getName = function () {
    console.log(4);
}

function getName() {
    console.log(5);
}

Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

  ok,下面我來一點一點分析一下這段代碼到底要做個啥。首先第一個

Foo.getName(); //2

  第一個是2這肯定是沒問題的。

我們繼續往下

getName(); //4

  第二個為4的原因為啥不是5呢,這就涉及到變量提升的問題了,因為函數聲明會提升到執行環境的頂部,而函數表達式只有變量var getName會提升看起來就像是這樣

function getName(){
   console.log(5);
}
var getName;

getName = function(){
  console.log(4);    
}

  所以函數聲明getName會被蓋掉,所以這里是4;

ok,繼續往下看

Foo().getName(); //1

  這。。。。其實仔細看的話也是可以看出來的,我們在執行Foo()函數的時候getName這個變量提升到外部的全局作用域中了,因為在js中,如果對於一個變量沒用用var 或者 let等聲明的話,他就默認是全局屬性,就是window對象的一個屬性。所以在這里我們的全局的getName又被改了

因為我們Foo()執行的時候返回了this而這里的this就是window對象,關於為什么是window這里不再展開講,不然就寫不完了。。。。

我們需要知道的是在瀏覽器中所有全局的聲明都是window對象的屬性和方法,所以這里我們調用this.getName()就會返回1了。

這里需要注意的是如果你是在node環境下打印這些值的話,這里是會報錯的,因為在node環境下全局對象為global對象,而它區別window對象一個重要區別是,聲明的函數,變量不是global的屬性,所以你就找不到getName這個方法;而且會影響下一個的取值,下一個就會是4了。

 

接下來我們再一次執行

getName(); // 1

  因為已經被修改了,所以不難看出來。接下來

new Foo.getName(); //2

  在這里我們通過new 來返回一個 Foo.getName 的實例。因為new的過程中一步很重要的操作是通過call將this綁定到實例對象上,並將實例對象返回,ok,既然有call的過程那么就很容易明白他這里輸出了2;

我們可以驗證一下結果

var bar = new Foo.getName();
bar.__proto__.constructor === Foo.getName //true

  這樣就能更直觀的看出,我們這樣通過原型鏈看出他是Foo.getName的實例;

接下來

new Foo().getName(); //3

  在這里我們通過new Foo()操作返回一個實例對象,這樣我們就可以通過原型鏈__proto__找到getName這個方法並執行他。

最后

new new Foo().getName(); //3

  這就是最讓人懵逼的地方,他到底在干啥呢,其實他和倒數第三個很像,他其實是對Foo().getName這個函數進行了實例化,具體可以看倒數第三個,所以這里會輸出3

而且我們可以在控制台上打印一下

var bar = new new Foo().getName();

打印這個bar看下結果吧。

這道題大致就是這樣,如果本人有寫錯的地方,還望指出,畢竟功力尚淺,歡迎留言進行交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM