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();
由于經常有人拿這個面試提問所以整理了一下保存起來
解析:
1、Foo.getName(); //2
Foo是一個函數,也可以說是一個對象,所以它也可以掛載一些屬性和方法。
所以結果執行的是Foo對象的一個叫做getName()的屬性,而1、4、5中的getName都是作為函數存在,所以可以排除1、4、5
剩下兩個中,2是Foo對象自身的屬性,3是Foo對象原型鏈上的屬性,而自身屬性的優先級高于原型鏈上的屬性,所以執行結果是2
2、getName(); //4
結果執行的是getName函數,而題目代碼中有3個相關函數,分別是1、4、5
1中的getName是定義在Foo函數中的函數,由于Foo尚未執行,因此它沒有暴露出來,無法被外部調用,可以排除
4和5都可以被正常調用,關鍵在調用先后問題
由于5是普通函數(優先級最高),4是匿名函數;js解析時會將5提前至最上方優先解析,而后面解析的4會將5覆蓋,所以執行結果是4
3、Foo().getName(); //1
結果執行的是Foo函數,Foo函數中有個返回值是this;this被普通函數調用后,指向的對象一定是window對象,所以此處的結果已經可以解析為window.getName(),即調用getName()函數,所以最后執行的就是window.getName,所以輸出1;
4、getName(); //1
在上面已經更改全局的getName,執行getName即是執行window.getName;所以依然是1
5、new Foo.getName(); //2
new 操作符在實例化構造器的時候,會執行構造器函數,也就是說,foo.getName會執行,輸出2
6、new Foo().getName(); //3
new操作符的優先級較高,所以會先new foo()得到一個實例,然后再執行實例的getName方法,這個時候,實例的構造器里沒有getName方法,就會執行構造器原型上的getName方法
7、new new Foo().getName(); //3
先執行new foo()得到一個實例,然后在new 這個實例的getName方法,這個時候會執行這個方法,所以輸出3