程式碼如下:
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(); //2 getName(); //4 Foo().getName(); //1 getName(); //1 new Foo.getName(); //2 => new (Foo.getName)() new無引數列表 new Foo().getName(); // 3 => (new Foo()).getName(); //new有引數列表 new new Foo().getName(); //3 => new ((new Foo()).getName)() //new有引數列表
Foo.getName()
輸出結果為:2
原理:他呼叫的是Foo的靜態方法(如果C#、java等後端語言來說),其實是因為Javascript中的Function本身就是Function和Object的結合,所以function既是函式,也是物件。在這裡Foo就是執行了他物件上的一個function而已。
getName()
輸出結果為:4
原理:可能你會想為什麼不是5,function變數會提升到作用域的頂部,而var定義的則不會,所以var宣告的覆蓋掉function宣告。所以結果為4
Foo().getName()
輸出結果為:1
原理:Foo()是函式呼叫,Foo執行體中對getName進行了重新賦值(全域性的getName,根據作用域鏈向上查詢),返回的this為window(Foo執行時沒有呼叫,預設為全域性),然後.getName()呼叫了全域性的getName(也就是被Foo執行體重寫的getName),所以結果為:1
getName()
輸出結果為:1 原理:因為Foo執行體中對全域性getName重寫了,這時呼叫的又是全域性的getName。所以結果為:1
new Foo.getName()
輸出結果為:2
原理:
- 由於new無參,與new有參的運算優化級一樣。new有參的與.運算子同一級別,而new無參的低一個級別。所以會先執行.運算子選擇到Foo的靜態方法getName
- 然後執行new,獲得的是Foo.getName的一個例項。所以輸出結果為:2
new Foo().getName()
輸出結果為:3
原理:
- 由於new是有參的,與.運算子同級,按照從左向右的執行順序,先執行new Foo()。
- new Foo()是需要值得我們的注意,因為他有一個返回值。存在返回值分為兩種情況:
- 無返回與返回為基本型別是一樣的效果:返回都是例項物件(也就是當前的this)
- 返回為引用型別:返回的為這個引用型別的物件,此時例項物件被替換了(也就是當前的this沒有返回)。因數new Foo()返回是例項物件
- .getName():選擇是上一步例項的此方法,所以輸出結果為:3
new new Foo().getName()
輸出結果為:3
原理:主要是運算子優先順序的考查,例項開發中應該不會這樣直接的用到。首先new有參,然後.getName(.運算子)(為什麼是.運算子,這是因為new無參級別低一個檔次),再則new有參。