bind()

API

bind() 创建一个新的函数,新函数中的 this 绑定为 bind() 的第一个参数,其余参数作为新函数的参数;供之后调用使用。

function foo(b) {
    console.log(this.a + b)
}

var obj = {
    a: 0
}

// 创建了一个新函数
var bar = foo.bind(obj, 1)

// 再进行调用
bar()   // 1

如果使用 new 构造调用 bar ,那么 bind 绑定是无效的:

function foo() {
    console.log(this.a)
}

var obj = {
    a: 0
}

var a = 'oops, global'

// 无效绑定
var bar = foo.bind(obj)

// 使用 new 调用
new bar()   // undefined, 注意不是绑定到了全局,而是绑定到一个新的空对象上了

虽然使用 new 调用会忽略 this ,但是后续传入的参数,在 new 调用时会被正确传入

实现细节

bind() 函数会创建一个新的绑定函数,它包装了原始函数;绑定函数内部有如下几个属性:

  • [[BoundTargetFunction]] - 被包装的原始函数

  • [[BoundThis]] - this 绑定的对象

  • [[BoundArgumengts]] - 传入的剩余参数

调用绑定函数时,会调用 [[BoundTargetFunction]] 上的内部方法 [[call]] ,就像:Call(boundThis, args)

应用

柯里化

利用 bind() 可以创建一些预设好参数的函数:

正如上文所提,这里传给 bind() 的 thisArg 最好是一个 DMZ 对象,这样更加安全

配合 setTimeout

前文提到过,在没有 ES6 的箭头函数时,回调函数中的 this 容易泄漏到全局对象上。我们可以用 bind() 包装一个回调函数,从而指定这个回调函数中的 this

手写实现 bind()

根据 bind() 实现的功能:

按照前面的例子,可以测试下:

Last updated