首先,先来总结一下这三者的共同点与区别:
- 三者都是为了改变
this
的指向 call
与apply
其实差不多,都是一次性传入所有参数,调用后马上执行对应的函数,只是前者接收的是参数列表,但后者接收的是一个数组,代码实现中,除了接收参数不同,其他完全一致bind
返回一个改变了this
指向的函数,在调用过程中,可以先传入部分固定参数,动态参数可以在调用返回的函数再传入,即可以分开多次传入参数,且返回的函数不会立即执行,开发人员可以根据需求来进行调用返回的函数
注意: 在实现过程中,一定要考虑到传入的对象为null
、undefined
、原始类型的情况,详情请看代码。
代码如下( call):
function test(a, b) {
console.log('test', this, a, b);
return a + b;
}
Function.prototype.myCall = function (ctx, ...args) {
// 由于js会在两种环境下运行:浏览器(window)和Node,故使用globalThis
ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx);
let uniqueKey = Symbol('test');
Object.defineProperty(ctx, uniqueKey, {
enumerable: false,
value: this
});
return ctx[uniqueKey](...args);
};
let res = test.myCall({}, 12, 13);
console.log('res = ', res); // 25
代码如下( apply):
function test(a, b) {
console.log('test', this, a, b);
return a + b;
}
Function.prototype.myApply = function (ctx, args) {
// 由于js会在两种环境下运行:浏览器(window)和Node,故使用globalThis
ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx);
let uniqueKey = Symbol('test');
Object.defineProperty(ctx, uniqueKey, {
enumerable: false,
value: this
});
return ctx[uniqueKey](...args);
};
let res = test.myApply ({}, 12, 13);
console.log('res = ', res); // 25
代码如下( bind):
function test(a, b) {
console.log('test', this, a, b);
return a + b;
}
Function.prototype.myBind = function (ctx, ...args1) {
// 由于js会在两种环境下运行:浏览器(window)和Node,故使用globalThis
ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx);
let uniqueKey = Symbol('test');
Object.defineProperty(ctx, uniqueKey, {
enumerable: false,
value: this
});
return function (...args2) {
return ctx[uniqueKey](...args1, ...args2);
};
};
let backFunc = test.myBind({}, 12);
let res = backFunc(88);
console.log('res = ', res); // 100
ps:如有不足,欢迎点评,谢谢!