示例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
答案 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无法更加不同。 storeMyName
和storeMyName2
包含将来调用的函数,而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