1. 程式人生 > >JS面向物件經典題目(一)

JS面向物件經典題目(一)

感覺這道題目是面向物件中比較經典了題目了.先上程式碼,然後分析

1 function Foo(){
2        getName = function(){console.log(1);};
3        return this;
4    }
5    Foo.getName = function(){console.log(2);};
6    Foo.prototype.getName = function(){console.log(3);};
7    var getName = function(){console.log(4);};
8    function getName
(){
console.log(5);} 9 Foo.getName();//2 10 getName();//4 11 Foo().getName();//1 12 getName();//1 13 new Foo.getName();//2 14 new Foo().getName();//3 15 new new Foo().getName();//3

做這道題時,首先要明白一點:就是一開始的函式申明,function Foo(),在沒有呼叫之前,始終是不會執行的.
1.Foo.getName()輸出2!
此處函式Foo()沒有呼叫,不執行函式,後面的輸出均於此函式什麼時候呼叫有密切關係.
此處的Foo是一個例項化物件,跟1行處的Foo除了同名再無其他關係.所以直接找到第5行處.這裡第5行表示給Foo物件新增一個輸出為2的方法.
2.getName()輸出4.
此處直接呼叫getName(),1行處的函式未執行,從上往下尋找,首先找到
第7行處,定義的getName物件.
3.Foo().getName()輸出1
此處先執行Foo(),這裡就呼叫第1行的函數了,執行後return一個this,這裡呼叫Foo()的是window,所以this就指window。後面相當於window.getName()就直接找到函式內部getName()方法了.
4.getName()輸出1
因為在3中已經執行過Foo()函數了,函式內部內容有效.getName()無直接寫明呼叫物件,此處呼叫的物件就是window,函式體內部,getName也並未重新定義,而是一個全域性的getName(即window的方法),此處直接找到第二行處.
5.new Foo.getName()輸出2
這裡涉及到運算子的優先級別:’運算的()’>’.’> ‘new’||’函式呼叫的()’ 。
運算優先順序表


所以先執行5行處 Foo.getName()得到function(){console.log(2);}然後在 new function(){console.log(2);}
6.new Foo().getName()輸出3
此處,先函式呼叫Foo(),接著執行new Foo(),再用new得到的這個例項化物件執行屬性getName(),而getName()是通過6行處的原型鏈來定義的,所以找到第6行.
7.new new Foo().getName()輸出3
此處有2個new,先執行右邊的new Foo()得到一個例項化物件,這時,就無法執行左邊的new了(總不至於new 後邊跟一個例項物件吧),只能先執行後邊的 .getName()得到一個函式,最後執行最左邊的new.