call和apply
基本上就是入参格式的不同
const _call = function (context, ...resArgs) {
context = context instanceof Object ? context : {};
context["fn"] = this;
const result = context["fn"](...resArgs); // 带参执行
delete context.fn;
return result;
};
Function.prototype.call = _call
const _apply = function (context, resArgs) {
context = context instanceof Object ? context : {};
context["fn"] = this;
const result = context["fn"](...resArgs); // 带参执行
delete context.fn;
return result;
};
Function.prototype.apply = _apply
call: 接收参数列表
call(context, ...resArgs) => context.fn(...resArgs)
call(obj, 1,2,3) => obj.fn(1,2,3)
apply: 接收数组
call(context, resArgs) => fn(context, ...resArgs)
call(obj, [1,2,3]) => obj.fn(1,2,3)
主要逻辑:
context["fn"] = this
this为调用call/apply的对象,即要执行的函数,赋值给传入的上下文
const result = context["fn"](...resArgs)
带参执行,此时函数执行的上下文已经变成了传入的context
delete context.fn;
删掉函数,避免污染传入的上下文
bind
const _bind = function (context, ...resArgs) {
let fnc = this; // 获取要执行的函数
return function () {
fnc.call(context, ...resArgs, ...arguments); // 合并bind时的参数和调用函数时的参数
};
};
Function.prototype.bind = _bind;
大同小异,只是返回的是待执行的函数
注:不能用arrow function, 不然获取不到执行函数this ~
more
上述重写都是挂载到原型上,也可以写成手动传入上下文,这种写法可以更好的作为模块导出
call (apply同上)
export const call = function (fnc: Function, context: any, ...resArgs) {
context = context instanceof Object ? context : {};
context["fn"] = fnc;
const result = context["fn"](...resArgs);
delete context.fn;
return result;
};
bind 使用上面写好的call
export const bind = function (fnc: Function, context, ...resArgs) {
return function () {
call(fnc, context, ...resArgs, arguments);
};
};
let obj = { name: 'jenson' }
function fn() { console.log(this.name) }
bind(fn, obj)() // jenson