实现 call
Function.prototype.myCall = function(context) {//首先context为可选参数,如果不传,上下文默认为window;
if(typeof this !== 'function'){
throw new TypeError('Error');
}
context = context || window;
context.fn = this;//创建fn属性,并将值设置为需要调用的函数
const args = [...arguments].slice(1);//因为call可以传入多个参数作为调用函数的参数,所以要将参数剥离
const result = context.fn(...args);//调用函数
delete context.fn;//将对象上的函数删除
return result;
};
实现 apply
Function.prototype.myApply = function (context) {
if(typeof this !== 'function'){
throw new TypeError('Error');
}
context = context || window;
context.fn = this;//创建fn属性,并将值设置为需要调用的函数
let result;
//处理参数和 call 有区别
if(arguments[1]){
result = context.fn(...arguments[1]);//调用函数
}else {
result = context.fn()
}
delete context.fn;
return result;
};
实现 bind
Function.prototype.myBind = function (context) {
if(typeof this !== 'function'){
throw new TypeError('Error');
}
const _this = this;
const args = [...arguments].slice(1);
//返回一个函数
return function F () {
//因为返回了一个函数,可以new F(),所以需要判断
if(this instanceof F){
return new _this(...args,...arguments);//通过 new 的方式,不会被任何方式改变 this,
// 所以对于这种情况我们需要忽略传入的 this
}
return _this.apply(context,args.concat(...arguments));//直接调用函数,选择apply的方式实现,
// 对于参数需要注意的是:因为bind可以实现.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,
// 于是就有了这样的实现 args.concat(...arguments)
}
};
以上内容结合个人理解与相关资料,如有错误,请批评指正。