重构call、apply、bind
逻辑梳理:
第一个参数为改变后this指向,第一个参数不存在则默认指向window
call后续参数不限制,apply只能拥有两个参数,且第二个参数必须为类数组
call与apply改变this指向后调用函数,bind改变this指向后返回一个新函数,不执行
call、apply、bind所有函数均可调用,因此,这三个方法均为函数原型对象上的属性
call
Function.prototype.myCall = function (invoke) {
if(typeof this !== "function") throw new TypeError(`Uncaught TypeError: ${this}.call is not a function`);
invoke = invoke || window;
invoke.fn = this;
let args = [...arguments].slice(1);
let result = invoke.fn(args);
delete invoke.fn;
return result;
}
apply
Function.prototype.myApply = function(invoke){
if(typeof this !== "function") throw new TypeError(`Uncaught TypeError: ${this}.apply is not a function`);
invoke = invoke || window;
invoke.fn = this;
let result = arguments[1] ? invoke.fn(...arguments[1]) : invoke.fn();
delete invoke.fn;
return result;
}
bind
Function.prototype.myBind = function (invoke) {
if (typeof this !== "function") throw new TypeError(`Uncaught TypeError: ${this}.bind is not a function`);
let args = [...arguments].slice(1);
let newThis = this;
return function F(){
return this instanceof F ? new newThis(...args, ...arguments) : newThis.apply(invoke, args.concat(...arguments))
}
}