對於常年使用C++,C#,Java等這些物件導向語言的程式員來說,幾乎天天都和this打交道。在這些語言裡,this含義非常明確,就是指向當前的對象執行個體,我們用起來也是相當的放心。然而,到了JavaScript這個動態語言裡,this的寫法沒變,但是其含義卻大大地不同了,下面用執行個體說明,使用瀏覽器為Firefox14.0.1.
例子一:
(1)源碼
<!DOCTYPE html><html><body> <script> alert(this); </script></body></html>
(2)執行結果
(3)分析與結論
此時,JS引擎會自動產生一個window對象的成員函數,把上述執行代碼放入此函數執行,此時this指向對象window。此時與C++,JAVA,C#的執行個體成員函數類似。
例子二:
(1)源碼
<!DOCTYPE html><html><body><script>function f() {alert(this);}f();</script></body></html>
(2)執行結果
(3)分析與結論
此例本質上與例子一相同,其中f();其實等價於window.f();也是通過window對象去調用成員函數,此時this仍指向window對象。此時與C++,JAVA,C#的執行個體成員函數類似。
例子三:
(1)源碼
<!DOCTYPE html><html><body><script>function f(name) {this.name = name;}var a = new f('葉詩文');alert(a.name);</script></body></html>
(2)執行結果
(3)分析與結論
此時,f()被當做建構函式來執行,函數體內的this此時指向被新構造出來的對象a。此時,與C++,JAVA,C#的建構函式類似。
例四:
(1)源碼
<!DOCTYPE html><html><body><script>function f() {alert(this.name);}f.apply({name: '葉詩文'});</script></body></html>
(2)執行結果
(3)分析與結論
通過apply方式調用時,函數內的this是通過參數控制的,apply()的第一個參數就指定了this的值。在C++,JAVA,C#中不存在這種特性。
例五:
(1)源碼
<!DOCTYPE html><html><body><script>var name = '劉翔';var a = {name: '葉詩文'};a.f = function() {alert(this.name);(function(){alert(this.name);})();}a.f();</script></body></html>
(2)執行結果
(3)分析與結論
此處的f()函數是作為對象a的成員函數來執行的,所以f函數體內的this指向對象a;而其中嵌套的匿名函數沒有顯示指定其所屬對象,則自動屬於window對象,其執行是作為window的成員函數來執行,故其函數體內的this指向window。
總結:
(1)JavaScript中,執行代碼必須放入函數中,如果沒有顯示寫入函數中,則代碼會自動被放入window的某個成員函數中;
(2)JavaScript的函數都是成員函數,一定屬於某個對象,如果沒有顯示指定此對象,那麼這個函數就屬於window對象;
(3)JavaScript函數的執行方式有三種,一是作為成員函數來調用,此時函數體內的this指向函數所屬對象;二是作為建構函式來調用,此時函數體內的this指向通過此建構函式新建立的對象;三是通過apply或call調用,此時函數體內的this是被參數控制的。
(4)this的指向與定義函數的文法與位置無關,只與函數被調用的方式有關。