鍍金池/ 問答/HTML/ 函數(shù)就是對象嗎?對象就是函數(shù)嗎?跪求大shen詳解

函數(shù)就是對象嗎?對象就是函數(shù)嗎?跪求大shen詳解

哪位大神給我解釋下走到誤區(qū)了

var Foo=function(){
    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)};//被污染為1

function getName(){console.log(5)};
 
Foo.getName(); //2
getName();//4
Foo().getName();//1

getName();//1

//前幾步我都懂 就是到這最后三步我清楚為什么?
//1、不懂 new Foo后,如果說函數(shù)是對象(Foo  ==Foo())為何調(diào)getName()的值不同
new Foo.getName();      //2

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

clipboard.png

回答
編輯回答
孤巷
2017年11月8日 21:07
編輯回答
好難瘦

以下解釋場景為全局作用域下,而不是一個函數(shù)體內(nèi)
.成員訪問操作符優(yōu)先級高于new對象實例創(chuàng)建操作符號
new操作符的優(yōu)先級高于函數(shù)調(diào)用
函數(shù)(除了箭頭函數(shù)和生成器函數(shù))都可以作為構(gòu)造函數(shù),和new操作符結(jié)合使用

var Foo=function(){
    getName=function(){console.log(1)};//污染了 [A]
    return this;
}
Foo.getName=function(){console.log(2)};// [B]

Foo.prototype.getName=function(){console.log(3)};//[C]

var getName=function(){console.log(4)};//被污染為1 //[D]

function getName(){console.log(5)};//[E]
 
Foo.getName(); //2 [F]
getName();//4 [G]
Foo().getName();//1 [H]

getName();//1 [I]

//前幾步我都懂 就是到這最后三步我清楚為什么?
//1、不懂 new Foo后,如果說函數(shù)是對象(Foo  ==Foo())為何調(diào)getName()的值不同
new Foo.getName();      //2 [J]

new Foo().getName();    //3 [K]
new new Foo().getName();//3  [L]

[A] 定義了名Foo的函數(shù)對象,在函數(shù)體內(nèi)定義了一個名為getName的全局函數(shù)變量
[B] 為函數(shù)對象Foo設(shè)置了一個名為getName的屬性,這個屬性指向一個函數(shù)
[C] 為函數(shù)對象Foo的原型對象添加了一個getName屬性,這個屬性指向一個函數(shù)
[D] 定義了一個全局函數(shù)變量getName,指向一個匿名函數(shù),因為變量提升的關(guān)系getName申明放到頭部,而變量賦值會留在原地不動
[E] 通過函數(shù)申明的方式定義了一個名為getName,同樣因為提升的關(guān)系,函數(shù)聲明將被放到最頂部,實際達到的效果是這個函數(shù)聲明從來沒有出現(xiàn)過
[F] 調(diào)用Foo函數(shù)對象的getName方法,也就是是[B]定義的函數(shù),輸出2
[G] 調(diào)用[D]定義的函數(shù)變量getName執(zhí)行的函數(shù),輸出 4
[H] 執(zhí)行Foo函數(shù),此時全局函數(shù)變量getName被重新賦值,此時Foo函數(shù)返回的this指向的是全局對象,全局函數(shù)變量getName就是附在其上的,那么在全局對象上執(zhí)行g(shù)etName方法,輸出 1
[I] 全局函數(shù)變量getName的指向已經(jīng)通過[H]執(zhí)行被重新賦值了,指向

  getName=function(){console.log(1)};//污染了 [A]

輸出 1
[J] new Foo.getName();==>new (Foo.getName)();
Foo.getName返回一個函數(shù),通過new操作,此函數(shù)被當做構(gòu)造函數(shù)處理,函數(shù)執(zhí)行,輸出 2
[K] new Foo().getName();分解成2步:
第1步 new Foo() ==> someFooInstance
第2步 someFooInstance.getName()
此時的getName函數(shù)為[C]定義的函數(shù)
[L] new new Foo().getName(); ==> new (new Foo().getName)();
new Foo().getName返回的函數(shù)對象體為[C]定義的函數(shù),輸出 3

2018年4月28日 17:43