2016-12-30 37 views
29

示例1中的問題是'this'引用全局名稱而不是myName對象。爲什麼JavaScript bind()是必需的?

我明白使用bind()將它的值設置爲特定的對象,所以它解決了示例1中的問題,但爲什麼這個問題首先發生?它只是Javascript的創建方式嗎?

我也想知道爲什麼例如3解決了問題,例如在2和3之間的差異

this.name = "John" 
 

 
var myName = { 
 
    name: "Tom", 
 
    getName: function() { 
 
    return this.name 
 
    } 
 
} 
 

 
var storeMyName = myName.getName; // example 1 
 
var storeMyName2 = myName.getName.bind(myName); // example 2 
 
var storeMyName3 = myName.getName(); // example 3 
 

 
console.log("example 1: " + storeMyName()); // doesn't work 
 
console.log("example 2: " + storeMyName2()); // works 
 
console.log("example 3: " + storeMyName3); // works

+2

* 「是不是剛剛的Javascript創建的方式是什麼?」 *我想是的。 「this」的值是動態確定的,除非它是綁定或箭頭函數。不知道你想知道還有什麼期望[學習如何'這個'工作](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes /ch1.md)。 –

+0

[Javascript call()&apply()vs bind()?](http://stackoverflow.com/questions/15455009/javascript-call-apply-vs-bind) – azad

+3

*「我也想知道爲什麼示例3解決了問題「*'storeMyName'和'storeMyName2'包含* functions *,而'storeMyName3'包含調用*'myName.getName()'的*結果*。巨大差距。我在調用函數和'.bind'的方法之間進行了這種比較:https://twitter.com/fkling42/status/736228742008176640。也許它有助於某種方式。 –

回答

51

爲什麼JavaScript bind()是必需的?

this值由函數如何稱爲確定。如果它是誰調用的功能,那麼通常不需要使用.bind,因爲你可以控制如何調用該函數,因此它的this值。

但是,通常它是而不是你調用該函數。函數作爲回調函數和事件處理函數傳遞給其他函數。他們被其他代碼調用,你無法控制如何調用函數,因此無法控制this會引用什麼。

如果你的功能需要this設置爲一個特定的值,你是不是一個調用該函數,你需要的功能.bind到特定this值。

換句話說:.bind允許您設置值this而不調用功能現在

這裏是指/通話功能的比較:

    +-------------------+-------------------+ 
        |     |     | 
        |  time of  |  time of  | 
        |function execution | this binding | 
        |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
| function object |  future  |  future  | 
|   f   |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
| function call |  now   |  now  | 
|  f()  |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
|  f.call()  |  now   |  now  | 
|  f.apply()  |     |     | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 
|     |     |     | 
|  f.bind()  |  future  |  now  | 
|     |     |     | 
+-------------------+-------------------+-------------------+ 

我也想知道爲什麼實施例3解決問題和實施例2和3之間的差

實施例1/2和3不可能有更大的不同。 storeMyNamestoreMyName2包含函數,這在將來被調用,而storeMyName3包含在那一刻調用myName.getName()的結果


進一步閱讀材料:

+0

非常感謝您的幫助和資源。我是JavaScript新手,你對我的回答非常明顯。所以call()/ apply()與例3相同,除了getName()方法與對象分離時使用。 –

+0

基本上是的。如果一個函數是一個對象的屬性,那麼將該函數調用爲myName.getName()將隱式地將this設置爲myName。它相當於'myName.getName.call(myName)'。 –

5

bind()方法創建,調用它時的新功能,將其關鍵字設置爲提供的值,並在調用新函數時提供的任何參數序列之前提供給定的參數序列。

所以,當你執行var storeMyName = myName.getName;第一次,它需要全球name(this.name =「約翰」)

當您使用bind()功能,它開始參照當前定義的名稱封閉件(MYNAME在這種情況下),因此打印Tom

第三時間,因爲該函數被調用馬上其範圍是其自身的本地對象物的內部,從而在閉合打印值Tom

0

綁定是機制,通過它可以更改執行的上下文(這裏您的默認上下文是全局的)。

根據你的榜樣 -

var storeMyName = myName.getName; 

從上面一行是要執行在全球範圍內storeMyName功能,所以這個執行this.name將頂線(即全球性的/「約翰」)。

var storeMyName2 = myName.getName.bind(myName); 

對於上述行你明確改變執行上下文storeMyName2功能(說,我不想執行此功能作爲全局函數我想在myName對象的上下文中執行此功能,所以在這種情況下this.name將是「湯姆」)

var storeMyName3 = myName.getName(); // example 3 

而對於這個上面一行你只是執行上myName對象上下文的功能,更重要的是你是不是在執行storeMyName3,這就是爲什麼它的背景不是全球性的。

0

我喜歡的一個比喻,我從來沒有見過任何地方: 假設你有一個具有bar函數的foo對象。 當您將bar函數綁定到另一個變量(或將其作爲函數參數傳遞時,這對於回調來說更常見),您不是將函數與其封閉對象進行綁定/傳遞,而只是「nude」函數。 因此,使用「裸體」功能,this意味着全局對象。

一個小演示

var foo = "global foo"; //foo set on the global object 
var a = {foo : "object foo", bar : function(){return this.foo;}}; 
var bound = a.bar; 
console.log(bound());//returns "global foo", not "object foo" 

bound只是指向function(){return this.foo;}

相關問題