js 中的 call、apply、bind 笔记
apply call
Function.prototype.apply()
、Function.prototype.call()
call()
和 apply()
是 Function
的方法,它的第一个参数是 this
,第二个参数是是给 调用函数 传递的参数。call
和 apply()
都是为了改变某个函数运行时的 context
即上下文而存在的。
换句话说,就是为了改变函数体内部 this
的指向。
call()
需要把参数按顺序传递进去,而 apply()
则是 把参数放在数组里。他俩都是调用后立刻执行的
例如,有一个函数 fun
定义如下:
1 | window.color = "red"; |
其中
第一个参数 this
是你想指定的上下文,他可以任何一个 js
对象。
第二个参数是给 调用函数
传递的参数(如果调用函数没有参数就不传)。
如果 call()
方法没有参数,或者参数为 null
或 undefined
,则等同于指向全局对象。另外箭头函数无法使用 call()
apply()
bind()
,因为箭头函数中的 this
永远指向函数外最近的那个 this
,因此不会起作用。
返回值:使用调用者提供的 this
值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined
。
有参数的情况下
1 | window.name = 'mark' |
JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数明确知道数量时,用call()
,而不确定的时候,用apply()
,然后把参数 push
进数组传递进去。
bind
Function.prototype.bind()
bind()
方法返回一个绑定了 this
的新函数(原函数的拷贝),在 bind()
被调用时,这个新函数的 this
被指定为bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
call()
和 apply()
它们两个是改变 this
的指向之后立即调用该函数,而 bind()
则不同,它是创建一个新函数,我们必须手动去调用它。
通俗讲就是通过bind()
方法,强制绑定了 this
,绑定后的 this
不可改变
示例1:
示例2:
1 | const d = new Date(); |
上面代码中,我们将 d.getTime()
方法赋给变量 print
,然后调用 print()
就报错了。这是因为 getTime()
方法内部的 this
,绑定 Date
对象的实例,赋给变量 print
以后,内部的 this
已经不指向 Date
对象的实例了。
bind()
方法可以解决这个问题。
1 | const print = d.getTime.bind(d); |
上面代码中,bind()
方法将 getTime()
方法内部的 this
绑定到 d
对象,这时就可以安全地将这个方法赋值给其他变量了。
bind
方法的参数就是所要绑定 this
的对象,下面是一个更清晰的例子。
1 | const counter = { |
上面代码中,counter.inc
方法被赋值给变量 func
。这时必须用 bind()
方法将 inc()
内部的 this
绑定到 counter
,否则则会报错
this
绑定其他对象也是可以的
1 | const counter = { |
上面的代码中,bind()
方法将 inc()
内部的 this
绑定到 obj
对象。调用 func()
后,递增的就是 obj
内部的 count
属性。
bind()
还可以接受更多的参数,将这些参数绑定原函数的参数。
1 | const add = function (x, y) { |
上面代码中,bind()
方法除了绑定 this
对象,还将 add()
函数的第一个参数 x
绑定成 5
,然后返回一个新函数 newAdd()
,这个函数只要再接受一个参数 y
就能运行了。