Function.prototype.call.apply、Function.prototype.apply.call、Function.prototype.apply.apply 同理
const obj1 = {
hello: 'obj1',
sayHello() {
console.log(this.hello);
},
};
const obj2 = {
hello: 'obj2',
};
const callbackName = Symbol('call-callback');
/* 代码一 */
obj1.sayHello.call(obj2);
/* 分解 */
obj2[callbackName] = obj1.sayHello;
obj2[callbackName](/* 参数 */);
delete obj2[callbackName];
/* 代码二 */
Function.prototype.call.call(obj1.sayHello, obj2);
/* 分解 */
obj1.sayHello[callbackName] = Function.prototype.call;
obj1.sayHello[callbackName](obj2);
/* 等价于,因为调用call的时候也是去原型链找 */
console.log(obj1.sayHello.call === obj1.sayHello[callbackName]);
obj1.sayHello.call(obj2); // 循环到 代码一
实现call、apply
Object.defineProperty(Function.prototype, 'myCall', {
value(context) {
const singleTag = Symbol('call-callback');
context[singleTag] = this;
/**
* 设置参数,没用展开操作符
* 只能参考一下,使用arguments了 */
let argsPointer = '';
for (let i = 1; i < arguments.length; i++) {
argsPointer += `arguments[${i}],`;
}
// argsPointer.slice(0, -1);
const returnVal = eval(`context[singleTag](${argsPointer})`);
delete context[singleTag];
return returnVal;
},
});
Object.defineProperty(Function.prototype, 'myApply', {
value(context, args) {
const singleTag = Symbol('apply-callback');
context[singleTag] = this;
let returnVal = undefined;
if (!args) {
returnVal = context[singleTag]();
} else {
let argsPointer = '';
for (let i = 0; i < args.length; i++) {
argsPointer += `args[${i}],`;
}
// argsPointer.slice(0, -1);
returnVal = eval(`this.myCall(context,${argsPointer})`);
}
delete context[singleTag];
return returnVal;
},
});
if (1) {
const obj1 = {
hello: 'obj1',
sayHello(a, b, c) {
console.log(a, b, c);
console.log(this.hello);
},
};
const obj2 = {
hello: 'obj2',
};
obj1.sayHello.myCall(obj2, 1, 2, 3);
obj1.sayHello.myApply(obj2, [1, 2, 3]);
}