Javascript 如何知道何时在JS中的函数上使用.bind()?

Javascript 如何知道何时在JS中的函数上使用.bind()?,javascript,function,scope,this,bind,Javascript,Function,Scope,This,Bind,(我知道这个问题,但答案并没有告诉我需要知道什么。) 我遇到过这样的情况:我需要在JavaScript中的函数上使用,以便将this或局部/类变量传递给函数。然而,我仍然不知道什么时候需要它 确切地说,知道函数中何时会或何时不会有此或局部/类变量的标准是什么?你如何解释这一点? 例如: 当创建、包装或传递新的匿名函数(){}时 当使用类成员函数、类getter/setter函数或老式的原型函数成员函数(作为类的函数)时 在全球范围内 在for或forEach循环中,或在其任何变体中 在闭包中是

(我知道这个问题,但答案并没有告诉我需要知道什么。)

我遇到过这样的情况:我需要在JavaScript中的函数上使用,以便将
this
或局部/类变量传递给函数。然而,我仍然不知道什么时候需要它

确切地说,知道函数中何时会或何时不会有
或局部/类变量的标准是什么?你如何解释这一点?

例如:

  • 当创建、包装或传递新的匿名
    函数(){}
  • 当使用
    成员函数、
    getter/setter函数或老式的
    原型函数
    成员函数(作为类的函数)时
  • 在全球范围内
  • for
    forEach
    循环中,或在其任何变体中
  • 在闭包中是外部功能还是内部功能
  • 在各种JS操作中,例如
    Array.prototype.forEach.call()
    [].forEach.call()
  • 在各种JS库和脚本中,哪些可能有自己的自定义实现

我提出这一要求的主要原因是要意识到潜在的陷阱,避免依赖于反复试验。

在以下情况下,您需要使用
bind
(或类似方法):

  • 该函数是传统的(
    function
    关键字)函数或方法(在
    或对象文本中),并且
  • 调用该函数的方式不是显式设置
    this
    ,就是将其设置为不正确的值
原因是,对于传统函数或方法,
this
的值是由调用方设置的,不是函数本身的一部分。(详情及详情)

例如,考虑:

const obj = {
    method() {
        console.log(this === obj);
    }
};
现在,当我们执行
obj.method()
时,我们使用语法(调用属性访问器操作的结果)来指定此
将是什么,因此:

obj.method();
// => true
但假设我们这样做:

const m = obj.method;
现在,只需调用
m()
即可将
this
设置为默认的
this
在严格模式下未定义,全局对象在松散模式下):

我们可以为调用显式设置
的另一种方法是通过
调用
(及其表亲
应用
):

一些调用回调的函数允许您指定此
要使用的内容
forEach
会执行以下操作,作为回调后的参数:

[1].forEach(m, obj);
//          ^  ^^^---- the value to use as `this` in callback
//           \-------- the callback to call
// => true
下面是一个活生生的例子:

const obj={
方法(){
console.log(this==obj);
}
};
obj.method();
//=>true,`this`设置为`obj`是因为您在
//属性访问器的结果
常数m=对象方法;
m();
//=>false,`this`是默认的`this`而`this`不是
//通过语法或'call'显式指定`
m、 呼叫(obj);
//=>true,`this`是通过`call显式设置的`
[1] .forEach(m,obj);

//=>true,`this`是通过`forEach``thisArg`参数显式设置的
Mozilla开发者网络提供了一些关于指定不同情况的优秀文档:

  • 查看链接,了解
    如何在不同的上下文中工作,因此何时应使用
    绑定
    强制绑定函数的不同
    上下文

    通常,
    bind
    用于转移函数的“所有权”。具体地说,根据我的经验,它早在创建类之前就被用来强制将对象方法绑定到所讨论的对象。当使用箭头函数时,它也很有用,因为箭头函数有不同的上下文。

    将它们的答案归功于和,它们提供了有用的信息。以下4个答案/文章也很有帮助:

    然而,这些不是完全完整的,就是冗长的。因此,我决定将我的所有发现与代码示例结合在一起,形成一个答案


    在确定函数中是否存在
    或局部/类变量时,需要考虑几个因素:

    • 函数的包含范围
    • 调用链中的直接前导
    • 函数是直接调用还是间接调用
    注意:还有严格模式(产生
    未定义的
    ,而不是
    窗口
    对象)和箭头函数(不会从包含的范围更改


    以下是明确的规则:

    • 默认情况下,
      是全局对象,在浏览器世界中是
      窗口
    • 在全局范围内的函数中,
      仍将是
      窗口
      ,它不会更改
    • 或函数类(
      新函数(){}
      )中的成员函数内,在函数类的原型(
      funcClass.prototype.func=function(){}
      )内,在具有
      的相邻成员函数调用的函数内,或在对象中映射的函数内(
      {key:function>)(){}
      )或存储在数组中(
      [function(){}]
      ),如果函数是以类/对象/数组作为调用链中的直接前导直接调用的(
      class.func()
      this.func()
      obj.func()
      ,或
      arr[0]()
      ),
      引用类/对象/数组实例
    • 在任何闭包的内部函数(函数中的任何函数)、返回函数内部、调用链中以普通变量引用作为其直接前导调用的函数内部(,无论它实际位于何处!),或间接调用的函数内部(即传递
      m.call(obj);
      // => true
      
      [1].forEach(m, obj);
      //          ^  ^^^---- the value to use as `this` in callback
      //           \-------- the callback to call
      // => true