/**
* call
* @param { any } context 参数1: 修改后的this指向
* @param {...any} args 参数2: 函数参数
* @returns 返回执行结果
*/
Function.prototype.call = function call (context, ...args) {
// 如果 context 是 null 或者 undefined 时, 自动指向 window (规范中, 非严格模式)
context == null ? context = window : null;
// 如果 context 不是对象类型, 需要构造为对象类型: 只有对象类型才能设置属性
!/^(object|function)$/.test(typeof context) ? context = Object(context) : null;
// 创建一个能够保证唯一性的属性名, 避免污染原始对象
let self = this, res = null, key = Symbol('KEY');
// context[key] 此时就是 fn.call() 中的这个 fn 函数
context[key] = self;
// 执行
res = context[key](...args);
// 移除新增的属性
delete context[key];
return res;
}
/**
* bind
* @param { any } context 参数1: 修改后的this指向
* @param {...any} args 参数2: 函数参数
* @returns 返回修改this指向后的函数
*/
Function.prototype.bind = function bind (context, ...args) {
// 这里的 this 就是 fn.bind() 中的这个 fn 函数
let self = this;
/**
* @param {...any} params 参数1: 函数参数
*/
return function (...params) {
// 调用 call 即可
// 注: 需要把两部分参数拼接起来
return self.call(context, ...params.concat(args));
}
}
/**
* apply
* @param { any } context 参数1: 修改后的this指向
* @param { array } args 参数2: 函数参数
* @returns 返回执行结果
*/
Function.prototype.apply = function apply (context, args) {
// 这里的 this 就是 fn.apply() 中的这个 fn 函数
let self = this;
// 调用 call 即可
return self.call(context, ...args);
}
简单搞懂JS中的call、bind、apply 实现原理
最新推荐文章于 2022-10-14 14:44:20 发布