1.4.5 bind

创建一个新的绑定函数,其 this 值永久绑定到提供的对象上

ECMAScript 5 引入了 Function.prototype.bind()

调用 fn.bind(someObject) 会创建一个与 fn 具有相同函数体和作用域的新函数,但是对原函数体中的所有 this 值,新函数都会“永久绑定”到 bind() 的第一个参数上,而不管新函数的调用方式。

  • 新函数,a new bound function,一个新的绑定函数

  • 新函数的 this 值会“永久绑定”到第一个参数上,这意味着 bind only works once!

const module = {
    x: 33,
    getX: function () {
        return this.x;
    }
};

const unboundGetX = module.getX;
console.log(unboundGetX());

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());

以上代码的执行结果,如下:

undefined
33

1. bind() 函数

1.1 语法

  1. 参数 thisArg:传给目标函数的 this 值,当新的绑定函数被调用的时候使用

    • 在非严格模式下,null 和 undefined 会被替换成全局对象,原始值会被转换成相应的对象

    • 如果绑定函数是用 new 运算符创建的,则会忽略该参数

  2. 参数 arg1, …, argN(可选):添加到 arguments 之前的参数

  3. 返回值:具有指定 this 值和初始参数(如果提供的话)的给定函数的一个拷贝

bind() 函数会创建一个新的绑定函数(a new bound function),调用该绑定函数通常会导致其包装函数的执行。绑定函数会把传过来的参数都存下来(包括 this 值和前几个参数)作为它的内部状态,这些值都是预先存好的,而不是在调用的时候才传递。

1.2 新的绑定函数

以上代码的执行结果,如下:

1.3 只绑定一次

bind only works once,只绑定一次。

以上代码的输出结果,如下:

2. 常见用法

2.1 创建绑定函数

bind() 最简单的用法就是创建一个绑定特定 this 值的函数,而不管它的调用方式。

新手的一个常见错误就是,先把对象中的方法在变量里存起来,然后通过该变量来执行那个方法,并期待方法里的 this 值还能指向原来的对象。比如:

以上代码的执行结果,如下:

要想让中间变量 retrieveX 在执行的时候能依然访问到原始的 module 对象,可以给它创建一个绑定到 module 对象的绑定函数。如下:

2.2 预先指定参数

bind() 的另一个简单用法是,在创建函数的时候,可以预先指定初始参数。比如:

以上代码的执行结果,如下:

以上代码的执行结果,如下:

2.3 创建快捷方式

bind() 也能用于创建需要特定 this 值的函数的快捷方式。

比如想用 Array.prototype.slice() 把类数组对象转换成真正的数组,我们可以创建快捷方式:

使用 bind() 可以简化为:

在上面的代码中,slice()Function 对象的实例方法 apply() 的绑定函数,它将 this 值设置成了 Array 对象的实例方法 slice(),从而消除了额外的 apply() 调用。

2.4 setTimeout()

setTimeout() 中,this 值默认是 windowglobal 对象。

在类的方法中,this 值要么是类实例要么是类本身。当在类方法中使用 setTimeout() 时,如果要想让其回调里的 this 也指向类实例或类本身,就需要显式地绑定 this 值。比如:

2.5 用作构造函数

这部分是 bind() 用法的边缘情况,不推荐在线上环境使用(因为有更好的处理方法)

绑定函数也可以通过 new 运算符来构造,这样做就好像目标函数已经被构造好了一样,此时提供的 this 值会被忽略,而前置参数会被正常地传递给模拟函数。

以上代码的运行结果,如下:

3. 主要参考

Last updated