昨天搞完this指向后,我们顺藤摸瓜来,一起来实现个call方法吧。call、apply、bind中之所以选择call,首先,它简单些。其次,bind的实现需要借助call、apply。最后,就是我个人最常用call。那就让我们开始吧。
call回顾
具体实现前,我们需要回顾一下call的使用方法。相信只有真正掌握了怎么用的人,才更容易把它实现出来。
语法上,call函数接收可供选择的this值,以及不计数量的参数列表。例如:.call(thisArg, arg1, arg2, ...)。又或者,.call(undefined, arg1, arg2, ...)。
功能上,call提供新的this值给当前被调用的函数或者方法。当然,call为新this提供的函数、方法的来源可以是其他对象的函数方法。
使用上,处理修改this指向,它还可以实现继承。比如当你写一个函数,然后让另外一个新的函数去继承它。这样就不用在新函数中写重复代码了。
实现思路
实现前,需要实现的关键问题如下:
- 了解call从哪里来?要写在哪里?
- 如何修改this指向?
- 如何传递参数?
- 传入undefined情况怎么解决?
解决思路如下(注:与问题条目一一对应):
- javaScript函数都是Function构造函数的实例,所以yourfunction.call(),中的call一定来自于Function.prototype,因此我们只需要将自己要写的myCall挂载到Function原型上即可。
- 这里我们需要给目标对象创建一个新的属性,来承载被调用函数的引用地址。然后借用this的隐式绑定,就讲函数挂在到了新对象上。(不懂得小伙伴,看下面具体实现部分就懂了哈)
- arguments是一个函数内,对应传递给函数的参数的类数组对象。我们将它直接解构给待执行函数即可。
- 我们这里直接当做非严格模式即可,当this为空时,赋值称为window。
实现
有了上面思路梳理,感觉蛮清晰的,所以没加注释。有疑问的小伙伴,欢迎在下方评论。
let name = '今晚打老虎';
function yourFunction(x, y) {
console.log(this.name, x + y);
}
const YaoShen = {
name: 'YaoShen'
}
Function.prototype.myCall = function(obj, ...arg) {
obj.temFunc = this;
const result = obj.temFunc(...arg); //这里感兴趣的同学 可以考虑下兼容性
delete obj.temFunc;
return result;
}
yourFunction.myCall(YaoShen, 1, 2)
结束语
每天从头到尾,写一篇更文后。都收获了满满的成就感,也对老知识有了新认识。因为要拿出来讲,所以在语言上也有了进步。希望自己能坚持下去。感觉大家的一路同行,我们顶峰相见。
等苦尽甘来的那一天,山河星月都做贺礼。