为什么需要 JavaScript bind()?

IT技术 javascript this bind
2021-01-18 00:38:00

示例 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个回答

为什么需要 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() 的那一刻


进一步阅读材料:

非常感谢您的帮助和资源。我是 javascript 新手,你的答案对我来说非常明显。所以 call()/apply() 和示例 3 一样,只是在 getName() 方法与对象分开时使用?
2021-04-03 00:38:00
基本上是的。如果函数是对象的属性,则调用函数 asmyName.getName()将隐式设置thismyName它相当于myName.getName.call(myName).
2021-04-08 00:38:00

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

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

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

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

我喜欢的一个类比,我从未在任何地方见过:假设您有一个带有bar函数的 foo 对象当您将 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 只需指向 function(){return this.foo;}

绑定是您可以更改执行上下文(这里您的默认上下文是全局的)的机制。

根据您的示例-

var storeMyName = myName.getName;

从上面一行是你storeMyName在全局上下文中执行函数,所以对于这个执行this.name将是顶行(即全局一个/“约翰”)。

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

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

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

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