手写call、apply、bind函数

50 阅读1分钟
Function.prototype.ownCall = function (context, ...args) {
    if (typeof this !== 'function') {
        throw new Error(`${this}必须是函数`);
    }
    context = Object(context) || window;
    // key使用Symbol是为了防止对象中其他属性被覆盖
    let key = Symbol();
    context[key] = this;
    let result = context[key](...args);
    delete context[key];
    return result;
};

Function.prototype.ownApply = function (context, args) {
    if (typeof this !== 'function') {
        throw new Error(`${this}必须是函数`);
    }
    context = Object(context) || window;
    let key = Symbol();
    context[key] = this;
    let result = context[key](...args);
    delete context[key];
    return result;
};
// bind函数相当于在内部调用了一次call函数
Function.prototype.ownBind = function (context, ...args1) {
    if (typeof this !== 'function') {
        throw new Error(`${this}必须是函数`);
    }
    context = Object(context) || window;
    let key = Symbol();
    context[key] = this;
    return function (...args2) {
        let result = context[key](...args1, ...args2);
        delete context[key];
        return result;
    };
};
function fn1 () {
    console.log(this, arguments);
    console.log(1);
}
function fn2 () {
    console.log(this, arguments);
    console.log(2);
}
fn1.ownCall(fn2, 1, 2); // fn2 [1,2]
fn1.ownApply(fn2, [1, 2]); // fn2 [1,2]
var foo = {
    value: 'Node'
};

function bar (...list) {
    console.log(this.value);
    console.log(list);
}

bar.ownBind(foo, 1, 2)(3, 4);
bar.ownBind(null, 5, 6)(7, 8);
bar.ownBind(null)(5, 6, 7, 8);
bar.ownBind(undefined)(5, 6, 7, 8);