为什么JavaScript必须绑定()?
例1中的问题是'this'引用全局名称而不是myName对象。
我理解使用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
为什么JavaScript必须绑定()?
值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和3不能有更多的不同。 storeMyName
和storeMyName2
包含将来调用的函数,而storeMyName3
包含此时调用myName.getName()
的结果。
更多阅读材料:
bind()
方法创建一个新的函数,该函数在调用时将其关键字设置为提供的值,并在调用新函数时提供的任何前面给定的参数序列。
所以,当你执行var storeMyName = myName.getName;
第一次,它采用全球name
(this.name =“John”)
当你使用bind()
函数时,它开始引用在当前闭包中定义的名称(在这种情况下是myName),因此打印Tom
第三次,因为该函数马上被调用,所以它的作用域在它自己的本地对象内,因此在关闭Tom
打印该值
绑定是一种机制,通过它可以更改执行的上下文(这里您的默认上下文是全局的)。
根据你的例子 -
var storeMyName = myName.getName;
从上面来说,你是在全局上下文中执行storeMyName
函数的,所以对于这个执行, this.name
将是最上面的一行(即全局一个/“John”)。
var storeMyName2 = myName.getName.bind(myName);
对于上面的行,你显式地改变了storeMyName2
函数的执行上下文(通过说我不想执行这个函数作为全局函数,我想在myName
对象的上下文中执行这个函数,所以在这种情况下this.name
会是“汤姆”)
var storeMyName3 = myName.getName(); // example 3
对于上面这行,你只是在myName
对象上下文上执行函数,更重要的是你没有执行storeMyName3
,这就是为什么它的上下文不是全局的。