2014-01-10 76 views
0

以下部分:比較的Javascript範圍

var obj = { 
    name:'Tom', 
    sayHello:function() { 
     console.log("hello," + this.name); 
    } 
} 
var name = 'Kevin'; 

var method = obj.sayHello; 
method(); 

會得到輸出:

hello,undefined 

但是,如果改變var name = 'Kevin';name = 'Kevin';的輸出將是hello,Kevin。他們爲什麼不同?

回答

3

有兩個部分答案:

  1. 當您使用var method = obj.sayHello;,你是從obj去耦功能。當您調用某個方法時未給出明確的對象(即method()而不是obj.sayHello()),JavaScript會將this設置爲全局對象window

  2. 當您使用var name = 'Kevin'定義變量時,您正在創建一個具有函數作用域的局部變量。當您使用name = 'Kevin'定義變量時,您將創建一個全局變量,並附加到全局對象window。這與編寫window.name = 'Kevin'相同。

這兩件事結合起來意味着,內sayHellothiswindowthis.nameKevin

爲了解決這個問題,你需要使用bind,它返回你的方法與它的上下文固定到作爲參數提供的對象的副本bind

var method = obj.sayHello; 
new_method = method.bind(obj); 
new_method(); // hello, Tom 
3
sayHello:function() { 
     console.log("hello," + this.name); 
    } 

this這個函數指的是全局對象。當您將var name = 'Kevin';更改爲name = 'Kevin';時,將在全局對象中設置name變量。由於name設置爲全局,並且this爲全局,因此this.name指的是Kevin並且它打印hello,Kevin

1

如何調用函數將確定方法中的值this。在您的呼叫方式:

var method = obj.sayHello; 
method(); 

你正在失去你的sayHello()所以this被設置爲全局對象或undefined調用內部的obj參考this,未設置爲obj。因此,你得到的錯誤。

當你這樣做:

var method = obj.sayHello; 

所有,它是把一個參考sayHello功能在method變量。與obj存儲在method無關。所以,當你再調用method(),沒有對象的引用都這樣,而不是obj.sayHello()導致this設置爲obj,你只是調用sayHello()全部由自己不的this值設置爲obj


有多種方法可以解決它。

1)助手功能。

var method = function() {obj.sayHello()}; 
method(); 

2)使用.bind()

這裏.bind()將創建一個助手功能給你。

var method = obj.sayHello.bind(obj); 
method(); 

3)變更sayHello()方法

您可以更改sayHello()方法,因此不使用this指針(它工作正常,如果它是一個單獨的對象,但如果有多個實例):

sayHello:function() { 
    console.log("hello," + obj.name); 
} 
1

關鍵字this可能會很棘手。

如果您致電obj.sayHellothis關鍵字將引用obj。 當你寫method = obj.sayHello同樣的事情,寫作:

window.method = function() { console.log("hello," + this.name); } 

this關鍵字現在將參考window。 這就是爲什麼當你引用一個名稱爲name的變量時,你可以編寫window.name,它可以被你的函數找到。