apply call bind 这三个函数可以改变 this 的绑定,语法上有略微差别,可以看我很早之前的一篇文章做过简单的介绍 浅谈JavaScript中的apply、call、bind。
this 优先级
new关键字。函数被new调用,this指向由new新构建出来的这个对象- 函数通过
apply call bind调用,this指向绑定的对象 - 函数被调用时,
this指向调用的对象 - 默认。非严格模式情况下,this指向window, 严格模式下,this指向undefined。
总结一下优先级new 关键字 > apply call bind > 函数调用 > 默认
实现
我们既然要重写 apply,那前两个优先级是用不了的。我们使用第三个优先级——函数调用——改变 this 的指向。
先看下代码
1 | Function.prototype.myApply = function (context, args) { |
上面的代码忽略一些边界情况,实现了简易版的 apply。
看下使用的效果
1 | const person = { |
首先我们创建了一个 Symbol 对象作为 context 的 key,并把 this 赋值给他。此时的 this 值为 getName,因为是 getName 调用了 myApply,所以 this 指向调用者。
当我们以 context[key](...args) 这种方式调用 getName 时,this 指向了 context,因为是 context 调用了 getName 方法。借此完成了 this 值得转换。
call 和 bind 同理
call
1 | Function.prototype.myCall = function (context, ...args) { |
bind 的实现可以使用我们写的 call 函数。需要注意的是 bind 可以传参,新生成的函数也可以传参。
1 | Function.prototype.myBind = function (context, ...args) { |