有关这三个函数,在实际工作上,应该是用的比较多的,改变this指向的三种方式。call和apply类似,唯一的区别就是参数的传递方式有所不同而已,而bind函数是对需要执行的函数进行this绑定后返回一个新函数,且新函数的this不可再次改变。
call: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。
当前执行结果都是在非严格模式下。
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
const foo = function (a, b) {
console.log(a + b, this);
}
Function.prototype.myCall = function (thisArg, ...params) {
// null || undefined => if(thisArg == null)
if (thisArg === null || typeof thisArg === "undefined") return this(params);
// 原始类型的值 转为包装类
if (!/^(object|function)$/i.test(typeof thisArg)) thisArg = new Object(thisArg)
const sb = Symbol('fn');
// thisArg[sb] = this;
Object.defineProperty(thisArg, sb, {
// enumerable: false,
value: this,
configurable: true,
// writable: false
})
const res = thisArg[sb](...params);
// 此时删除了 但是在执行函数的过程时:控制台可以看见this中有该属性,
// 因为执行时 该属性还不能删除掉
delete thisArg[sb];
return res;
}
Function.prototype.myApply = function (thisArg, params) {
return this.myCall(thisArg, ...params);
}
Function.prototype.myBind = function (thisArg, ...params) {
// 使用箭头函数 this不可再次改变
return (...args) => {
this.myCall(thisArg, ...params, ...args);
}
}
foo.myCall({ name: '毛毛' }, 1, 2);
foo.myCall("2", 1, 2);
foo.myApply(20, [1, 4]);
foo.myBind({ name: "Mao" }, 1)(2);
foo.myBind({ name: "Mao" }, 1).bind(null)(12);