前言
apply、call和bind是显式绑定this的三种常用函数,也是面试最热门的考点。下面我们将从apply出发,带大家举一反三实现三种函数的简易版本。
本文默认你已经了解以上三种函数的行为,若不了解可以请先上MDN查看详细函数说明。
apply的实现
/*
* thisArg为函数运行时要使用的this值
* args 为一个数组或者类数组对象,是调用函数时的参数列表
*/
Function.prototype.apply = function(thisArg,args){
/*
* 当thisArg为undefined或null时
* 默认将thisArg指向window
* 注意仅在非严格模式下会有这种行为
*/
if (typeof thisArg === 'undefined' || thisArg === null){
thisArg = window;
}
// 为了防止原来的属性被覆盖,用Symbol去创建一个独一无二的值
const fnSymbol = Symbol();
// 这里this指向调用apply的函数
thisArg[fnSymbol] = this;
// 调用函数并接收返回值
const res = thisArg[fnSymbol](...args);
// 最后删除这个临时属性
delete thisArg[fnSymbol];
// 返回值
return res;
}
call的实现
实现call时只需要修改函数声明,注意这里使用了ES6的剩余参数,也可借助arguments去实现
- Function.prototype.apply = function(thisArg,args)
+ Function.prototype.call = function(thisArg,...args)
bind的实现
bind是一个高阶函数,它的实现可以借助之前的apply,下面给出最简的实现方式。
Function.prototype.bind = function(thisArg) {
// 法一:保存一下this指向,这里的this指向调用bind的函数
const self = this;
return function(...args){
return self.apply(thisArg,args);
}
// 法二:直接用箭头函数
return (...args)=>this.apply(thisArg,args);
}
后记
为了方便大家学习和记忆,上述源码都尽量以最简的形式进行呈现,在真正遇到面试的时候,大家只需牢记apply的实现便可以快速举一反三。同时,掌握它们的实现原理也是掌握this指向的关键。
关于我
喜欢聊天、喜欢分享、喜欢前沿的22届小菜鸡,初来乍到希望得到各位大佬的关注。能有实习/校招机会就更好啦!
个人公众号:鼠子的前端CodeLife