面向对象 - bind
bind 方法用于将函数体内的 this 绑定到某个对象,然后返回一个新函数
var d = new Date()
d.getTime() // 1578380274914
var print = d.getTime
print() // TypeError: this is not a Date object.
上面代码中,我们将 d.getTime
方法赋给变量 print
,然后调用 print
就报错了。这是因为 getTime
方法内部的 this
,绑定 Date
对象的实例,赋给变量 print
以后,内部的 this
已经不指向 Date
对象的实例了
bind
方法可以解决这个问题
var print = d.getTime.bind(d)
print() // 1578380274914
上面代码中,bind
方法将 getTime
方法内部的 this
绑定到 d
对象,这是就可以安全地将这个方法赋值给其他变量了
bind
方法的参数就是所要绑定 this
的对象,下面是一个更清晰的例子
var counter = {
count: 0,
inc: function() {
this.count++
}
}
var func = counter.inc.bind(counter)
func()
counter.count // 1
上面代码中,counter.inc
方法被赋值给变量 func
。这时必须用 bind
方法将 inc
内部的 this
,绑定到 counter
,否则就会出错
this
绑定到其他对象也是可以的
var counter = {
count: 0,
inc: function () {
this.count++
}
}
var obj = {
count: 100
}
var func = counter.inc.bind(obj)
func()
obj.count // 101
上面代码中,bind
方法将 inc
方法内部的 this
,绑定到 obj
对象。结果调用 func
函数以后,递增的就是 obj
内部的 count
属性
bind
还可以接受更多的参数,将这些参数绑定原函数的参数
var add = function (x, y) {
return x * this.m + y * this.n
}
var obj = {
m: 2,
n: 2
}
var newAdd = add.bind(obj, 5)
newAdd(5) // 20
上面代码中,bind 方法除了绑定 this 对象,还将 add 函数的第一个参数 x 绑定成 5,然后返回一个新函数 newAdd,这个函数只要再接受一个参数 y 就能运行了
如果 bind 方法的第一个参数是 null 或 undefined,等于将 this 绑定到全局对象,函数运行时 this 指向顶层对象(浏览器为 window)
function add (x, y) {
return x + y
}
var plus5 = add.bind(null, 5)
plus5(10) // 15
代码上面中,函数 add
内部并没有 this
,使用 bind
方法的主要目的是绑定参数 x
,以后每次运行新函数 plus5
,就只需要提供另一个参数 y
就能运行了
如果 bind
方法的第一个参数是 null
或者 undefined
,等于将 this
绑定到全局对象,函数运行时 this
指向顶层对象(浏览器为 window
)
function add(x, y) {
return x + y
}
var plus5 = add.bind(null, 5)
plus5(10) // 15
上面代码中,函数 add
内部并没有 this
,使用 bind
方法的主要目的是绑定参数 x
,以后每次运行新函数 plus5
,就只需要提供另一个参数 y
就足够了。而且因为 add
内部没有 this
,所以 bind
的第一个参数是 null
,不过这里如果是其他对象,也没有影响
bind
方法有一些使用注意点
每一次返回一个新函数
bind 方法没运行一次,就返回一个新函数,这会产生一些问题。比如,监听事件的时候,不能写成下面这样
element.addEventListener('click', o.m.bind(o))
上面代码中,click
事件绑定 bind
方法生成的一个匿名函数。这样会导致无法取消绑定,所以,下面的代码时无效的。
element.removeEventListener('click', o.m.bind(o))
正确的方法时写成下面这样:
var listener = o.m.bind(o)
element.addEventListener('click', listener)
// ...
element.removeEventListener('click', listener)
结合回调函数使用
回调函数时 JavaScript
最常用的模式之一,但是一个常见的错误是,将包含 this
的方法直接当作回调函数。解决方法就是使用 bind 方法,将 counter.inc
绑定 counter
var counter = {
count: 0,
inc: function () {
'use strict'
this.count++
}
}
function callIt(callback){
callback()
}
callIt(counter.inc.bind(counter))
counter.count // 1
上面代码中,callIt
方法会调用回调函数。这是如果直接把 counter.inc
传入,调用时 counter.inc
内部的 this
就会指向全局对象。使用 bind
方法将 counter.inc
绑定 counter
以后,就不会有这个问题,this
总是指向 counter
Last updated
Was this helpful?