重写内置call
/*
* 重写内置的CALL:把需要执行的函数和需要改变的THIS关联在一起
* + context.xxx=this obj.fn=fn;
* + context.xxx() obj.fn();
*/
Function.prototype.call = function call(context, ...params) {
// this->fn context->obj params->[10,20]
context == null ? context = window : null;
// 需要保证context必须是对象类型的值:只有对象才能设置属性
!/^(object|function)$/.test(typeof context) ? context = Object(context) : null;
let self = this,
result = null,
key = Symbol('KEY'); //新增的属性名保证唯一性,防止污染了原始对象中的成员
context[key] = self;
result = context[key](...params);
delete context[key]; //用完后移除自己新增的属性
return result;
};
function fn(x, y) {
console.log(this, x, y);
}
let obj = {
name: 'zhufeng',
fn: 100
};
fn.call(obj, 10, 20);
重写内置bind
柯理化思想「预处理思想」
Function.prototype.bind = function bind(context, ...outerArgs) {
// this->fn context->obj outerArgs->[10,20]
let self = this;
return function (...innerArgs) {
// innerArgs->[ev]
elf.call(context, ...outerArgs.concat(innerArgs));
};
};
function fn(x, y, ev) {
console.log(this, x, y, ev);
}
let obj1 = {
name: 'zhufeng'
};
/* document.body.onclick = function (ev) {
fn.call(obj, 10, 20, ev);
}; */
document.body.onclick = fn.bind(obj1, 10, 20);