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

为什么JavaScript bind()是必需的?,javascript,this,bind,Javascript,This,Bind,示例1中的问题是“this”指的是全局名称,而不是myName对象 我理解bind()在将其值设置为特定对象时的用法,因此它解决了示例1中的问题,但为什么首先会出现这个问题?这就是Javascript的创建方式吗 我还想知道为什么示例3解决了这个问题,以及示例2和示例3之间的区别 this.name=“John” var myName={ 姓名:“汤姆”, getName:function(){ 返回此名称 } } var storeMyName=myName.getName;//例1 var

示例1中的问题是“this”指的是全局名称,而不是myName对象

我理解bind()在将其值设置为特定对象时的用法,因此它解决了示例1中的问题,但为什么首先会出现这个问题?这就是Javascript的创建方式吗

我还想知道为什么示例3解决了这个问题,以及示例2和示例3之间的区别

this.name=“John”
var myName={
姓名:“汤姆”,
getName:function(){
返回此名称
}
}
var storeMyName=myName.getName;//例1
var storeMyName2=myName.getName.bind(myName);//例2
var storeMyName3=myName.getName();//例3
log(“示例1:+storeMyName());//不起作用
log(“示例2:+storeMyName2());//作品
log(“示例3:+storeMyName3);//作品
bind()
方法创建一个新函数,在调用该函数时,将其this关键字设置为提供的值,并在调用新函数时提供的任何参数之前提供给定的参数序列

因此,当您执行var storeMyName=myName.getName第一次使用全局
名称(this.name=“John”)

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

第三次,由于函数立即被调用,它的作用域在它自己的局部对象内,因此在闭包
Tom

为什么JavaScript bind()是必需的

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

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

如果您的函数要求将
this
设置为特定值,而您不是调用该函数的人,则需要
。将
函数绑定到特定的
this

换句话说:
.bind
允许您设置
的值,而无需立即调用函数

以下是引用/调用函数的比较:

                    +-------------------+-------------------+
                    |                   |                   |
                    |      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()
的结果


进一步阅读材料:


绑定是一种机制,通过它您可以更改执行的上下文(这里您的默认上下文是全局上下文)

根据你的例子-

var storeMyName = myName.getName;
从上面的一行可以看出,您正在全局上下文中执行
storeMyName
函数,因此对于此执行
this.name
将是最上面的一行(即global one/“John”)

对于上面的一行,您正在显式地更改
storeMyName2
函数的执行上下文(通过说我不想作为全局函数执行此函数,我想在
myName
对象的上下文中执行此函数,所以在这种情况下,
this.name
将是“Tom”)


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

一个我喜欢的类比,我在任何地方都没有见过: 假设您有一个带有
bar
函数的foo对象。 当您将bar函数绑定到另一个变量(或将其作为函数参数传递,这在回调中更常见),您没有绑定/传递带有其封闭对象的函数,而只绑定/传递“裸”函数。 因此,对于“裸”函数,
表示全局对象

小型演示

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
只要指向
函数(){return this.foo;}

“这就是创建Javascript的方式吗?”我想是的。
的值是动态确定的,除非它是绑定函数或箭头函数。不确定您还想知道什么。可能重复的“我也想知道为什么示例3解决了这个问题”
storeMyName
storeMyName2
包含函数,而
storeMyName3
包含调用
myName.getName()
的结果。差别很大。我比较了调用函数的方式和
.bind
:。也许这会有所帮助。这是一本很棒的书。它在JS中为我澄清了关于这个
的一切:非常感谢你的帮助和资源。我是javascript新手,你给了我一个很明显的答案。因此call()/apply()与示例3相同,只是在getName()方法与对象分离时使用?基本上是的。如果函数是对象的属性,则以
myName.getName()
的形式调用该函数将隐式地将
this
设置为
myName
。它相当于
myName.getName.call(myName)
var storeMyName3 = myName.getName(); // example 3
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"