Function.prototype.call
Function.prototype.call
方法用于指定函数调用指向的 this
指针,并分别提供参数作为指定函数的参数。
语法
语法:
call(thisArg: any, ...argArray: any[]): any;
参数
参数 | 说明 | 类型 |
---|---|---|
thisArg | 可选参数。调用函数时指向的 this 指针。 |
|
args | 可选参数。调用函数参数列表。 |
示例
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
const cheese = new Food('cheese', 5);
const robot = new Toy('robot', 40);
console.log(cheese);
// {
// category: "food",
// name: "cheese",
// price: 5,
// }
console.log(robot);
// {
// category: "toy",
// name: "robot",
// price: 40,
// }
兼容实现
实现步骤:
- 确保调用
call
方法的调用方为function
类型 - 参数:将参数数组转化为数组形式 ❗️(重点)
- 执行上下文:确保
context
执行上下文,用window
全局变量兜底 - 将
this
(调用方函数)赋值到执行上下文上,用Symbol
创建属性键名以防冲突 - 执行调用方函数,并保存调用结果 ❗️(重点)
- 删除调用方(执行上下文)的键值对
- 返回结果
Function.prototype.call = function (context) {
// context 是调用 call 的时候参数中的第一个参数
// 先判断当前的调用方是不是一个函数
if (typeof this !== 'function') {
throw new TypeError(`${this}.call is not a function.`);
}
// 保存调用方给的参数
const args = [...arguments].slice(1);
// 确定执行方的类型,因为可以传 null 和 undefined
context = context || window;
// 将调用方的内容保存为执行方的一个属性,为了保证不与执行方中的 key 键名重复
const fn = Symbol('fn');
context[fn] = this;
// 执行保存的函数,这个时候作用域就是在调用方的对象的作用域下执行,改变 this 的指向
const result = context[fn](...args);
// 执行完删除刚才新增的属性值
delete context[fn];
// 返回执行结果
return result;
};
由于 call
和 apply
的区别就在于传参的方式不同:
fn.call(ctx, arg1, arg2, arg3);
fn.call(ctx, [arg1, arg2, arg3]);
call
调用函数的参数是散列的形式apply
调用函数的参数是数组的形式