为什么JavaScript bind()是必要的?

时间:2016-12-30 05:49:21

标签: javascript this bind

示例1中的问题是'this'指的是全局名称而不是myName对象。

我理解使用bind()将this的值设置为特定对象,因此它解决了示例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

4 个答案:

答案 0 :(得分:58)

  

为什么需要使用JavaScript bind()?

this的值由 函数 决定。如果调用该函数,则通常不需要使用.bind,因为您可以控制如何调用该函数,从而控制其this值。

但是,调用该函数通常是。函数作为回调和事件处理程序传递给其他函数。它们由其他代码调用,您无法控制如何调用该函数,因此无法控制this将引用的内容。

如果您的函数需要将this设置为特定值而您不是调用该函数的函数,则需要将.bind函数设置为特定的this值。< / p>

换句话说:.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() 的结果

进一步阅读材料:

答案 1 :(得分:6)

  

bind()方法创建一个新函数,在调用时,将其this关键字设置为提供的值,并在调用新函数时提供任何前面提供的给定参数序列。

所以,当你第一次执行var storeMyName = myName.getName;时,它需要全局name(this.name =&#34; John&#34;)

使用bind()函数时,它会开始引用当前闭包中定义的名称(在本例中为myName),因此会打印Tom

第三次,因为函数被立即调用,它的作用域在它自己的本地对象中,因此在闭包Tom

中输出值

答案 2 :(得分:0)

Bind是一种机制,您可以通过该机制更改执行的上下文(此处默认上下文是全局的)。

根据您的示例 -

var storeMyName = myName.getName;

从上面开始,您在全局上下文中执行storeMyName函数,因此对于此执行this.name将是顶线(即全局一个/“John”)。

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

对于上面的行,你明确地改变storeMyName2函数的执行上下文(通过说我不想执行这个函数作为全局函数我想执行这个函数在myName对象的上下文中,所以在这种情况下this.name将是“Tom”)

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

对于上面的这一行,你只是在myName对象上下文上执行函数,更重要的是你没有执行storeMyName3,这就是为什么它的上下文不是全局的。

答案 3 :(得分:0)

我喜欢的类比,我从未见过任何地方: 假设你有一个带有serverURL函数的foo对象。 当您将bar函数绑定到另一个变量(或将其作为函数参数传递,这是回调的更常见情况)时,您不会使用其封闭对象绑定/传递函数,而只会绑定&#34;裸体&#34 ;功能。 因此,&#34;裸体&#34; function,bar表示全局对象。

小型演示

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

即可