一道面試題引起的慘案

先把面試題貼出來:

//請回答下面函數依次執行出什麼;
function Foo () {
    bar = function () {
        console.log(1)
    }
    return this;
}
Foo.bar = function () {
    console.log(2)
}
Foo.prototype.bar = function () {
    console.log(3)
}
var bar = function () {
    console.log(4)
}
function bar () {
    console.log(5)
}
Foo.bar();//2
bar();//4
Foo().bar();//1
bar();//1
new Foo.bar();//3
new Foo().bar();//3
new new Foo().bar();//3

剛看到這個問題,着實有點暈;不過細細分析下來,仍是有點門道的。


首先咱們來看一下這道題考察的是什麼

  • js的三種調用模式
  • 構造函數 原型

這裏涉及到js的三種調用模式;1.方法調用 2.函數調用 3.構造函數調用

接下來,咱們一一分析問題;

1. Foo.bar();//2

因爲瀏覽器在執行js時是同步去執行的,這裏能夠將Foo.bar看作 a ;這時就至關於:面試

a = function () {
    console.log(2)
}//因爲不是嚴格模式,這裏省略了聲明函數的關鍵字 var;
a();//2
2. bar();// 4

這個執行相應的函數體:瀏覽器

var bar = function () {
    console.log(4)
}
3. Foo().bar();// 1

Foo() 會去執行function Foo(){};同時會返回出一個全局的this;
Foo().bar() 執行函數Foo體內的bar函數函數

4. bar();// 1

第一個問題bar()執行的是函數:this

var bar = function () {
    console.log(4);
}//打印出來的是4

而在執行Foo().bar()時,Foo()會返回出來全局this,this內部的bar函數爲:prototype

bar = function () {
    console.log(1)
}

此時會覆蓋其他的bar函數code

5. new Foo.bar();// 2

構造函數調用模式;對象

Foo.bar = function () {
    console.log(2)
}
var foo =new Foo.bar();  //把Foo.bar看作爲總體如newFoo(){},newFoo就變成了構造函數
var foo = new newFoo();// foo => 2
6. new Foo().bar();// 3
使用new關鍵字,便會建立一個對象, 根據prototype屬性建立原型鏈,並以該對象爲this執行指定的(構造)函數。

咱們把須要的函數拿出來,看起來會爽的多;繼承

function Foo () {
    bar = function () {
        console.log(1)
    }
    return this;
}
Foo.prototype.bar = function () {
    console.log(3)
}
var foo = new Foo();
foo.bar() //3

看到這裏是否是就很清晰了;簡單的構造函數加原型的繼承;原型鏈

7. new new Foo().bar();// 3

結合上面兩問;該問題能夠這樣寫;原型

new new Foo().bar() => new foo.bar() =>new newFoo()//回到了用構造函數調用的模式;
相關文章
相關標籤/搜索