Javascript 的 `this` 是指什麼?
我們之前談過 scopes 和 closures. this
指的是當下這個 scope 的物件. 在瀏覽器裡最上層 scope 的物件是 window. 在 node.js 裡最上層是 global objects.
Javascript 是一個很自由的語言. 你可以用 functional programming
或者是 object oriented programming
的方式來撰寫. 用 functional programming
寫法通常是變數和 callbacks 傳來傳去, 用 closure 來存資料. this
通常用不太到. 但是 OOP
方式來撰寫的話就是一定要用到 this
了.
因為基本上這是一個 node.js 的教學, 所以我不會題太多 this
在 browser 端該如何運作. 從下面的範例裡我們可以看一下 this
和之前提到的 scope 有什麼關係.
var something, another; something = { x : 'x', print : function( callback ){ callback && callback.call( this ); console.log( this.x ); } }; another = { x : 'a', set_x : function(){ this.x = 'b'; } }; // situation a something.print( function(){ another.set_x(); }); // situation b something.print( another.set_x ); // situation c something.print( function(){ another.set_x.call( this ); });
結果
x b b
所以為何在 situation b
可以用 another
來設定 something
裡面的 x
呢? 那是因為我們在 something
的 print
method 裡用了 call
並帶入了一個參數 this
. 這樣一來 something
和 callback
就是屬於同一個 scope. 在 situation a
我們傳入了一個匿名函式當作 callback
並在這個匿名函式裡面呼叫 another.set_x
. 因為一個 function 就會產生一個新的 scope. 所以 callback
裡的 this
指到的不是 another
而是那個匿名函式. 要讓他正常運作的話只要像 situation c
一樣在匿名函式裡再用 call
一次來讓匿名函式和 another
屬於同一個 scope 就可以了.
常見錯誤
有一種常見的錯誤是當我們想在不同 scope 裡使用 this
, 而 this
卻指向不是我們要的 object. 所以我們呼叫的函式或是 property 常常會變成 undefined
. 這時只要在上層的 scope 裡把 this
指向一個變數, 舉例來說 self
. 這樣就可以在不同的 scope 裡來用 self
來代替 this
了.
var example = { name : 'who', wrong : function(){ setTimeout( function(){ console.log( this.name ); }, 0 ); }, right : function(){ var self = this; setTimeout( function(){ console.log( self.name ); }, 0 ); } }; example.wrong(); example.right();
結果
undefined who
這篇文章 Javascript call 以及 apply 有比較深入的介紹.