实现call
Function.prototype.myCall = function (targetObj, ...resule) {
// 判断传入对象的有无
targetObj = targetObj || window;
// 向传入对象上挂在this指向,此时this指向调用myCall函数
targetObj.fn = this;
// 在内部使用传入对象调用fn方法,这样可以实现更改this指向,指向为传入的目标对象
let value = eval('targetObj.fn(...resule)');
// 删除目标对象的fn方法
delete targetObj.fn
// 返回调用的结果
return value;
}
let obj = {
uname: 'Tom'
}
function demo(a, b){
console.log(this.uname, a, b);
}
demo();// undefined undefined undefined
demo.myCall(obj, 1, 2);
// Tom 1 2
实现apply (主体和call差不多, 不同的传入参数的方式)
Function.prototype.myApply = function (targetObj, resule) {
targetObj = targetObj || window;
targetObj.fn = this;
let value = eval('targetObj.fn(...resule)');
delete targetObj.fn
return value;
}
let obj = {
uname: 'Tom'
}
function demo(x, y){
console.log(this.uname, x, y);
}
demo();// undefined undefined undefined
demo.myApply(obj, [1, 2]);
// Tom 1 2
实现bind
Function.prototype.myBind = function (targetObj, ...resule) {
// 判断调用的对象是否是一个函数
if (typeof this !== "function") {
throw new Error("this must be a function");
}
// 创建变量保存this指向
// 此时this指向外部调用的函数
let self = this;
// 创建要返回的函数
let backFunc = function () {
// 先判断调用对象的this是否和本函数时同一个this
// 是则更改this指向到自身,(实际上最后返回的也只是this指向自身的函数)
// 不是则改变调用者this指向指向传入对象,将参数传递到调用的this中。
self.apply(this instanceof self ?
this : targetObj, resule.concat(Array.prototype.slice.call(arguments)));
}
// 判断调用是有原型
if(this.prototype) {
// 有则赋值原型到返回的函数上
backFunc.prototype = Object.create(this.prototype);
}
// 返回函数
return backFunc;
}
let obj = {
uname: 'Tom'
}
function demo(x, y){
console.log(this.uname, x, y);
}
demo();// undefined undefined undefined
demo.myBind(obj, 1, 2)();
// Tom 1 2