call,bind,apply实现

132 阅读1分钟

原文 www.cnblogs.com/echolun/p/1…

www.cnblogs.com/echolun/p/1…

// call
Function.prototype.call_ = function (obj) {
    obj = obj ? Object(obj) : window;
    obj.fn = this;
    // 利用拓展运算符直接将arguments转为数组
    let args = [...arguments].slice(1);
    let result = obj.fn(...args);

    delete obj.fn
    return result;
};
// apply
Function.prototype.apply_ = function (obj, arr) {
    obj = obj ? Object(obj) : window;
    obj.fn = this;
    let result;
    if (!arr) {
        result = obj.fn();
    } else {
        result = obj.fn(...arr);
    };

    delete obj.fn
    return result;
};

//bind
Function.prototype.bind_ = function (obj) {
    if (typeof this !== "function") {
        throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    };
    var args = Array.prototype.slice.call(arguments, 1);
    var fn = this;
    //创建中介函数
    var fn_ = function () {};
    var bound = function () {
        var params = Array.prototype.slice.call(arguments);
        //通过constructor判断调用方式,为true this指向实例,否则为obj
        fn.apply(this.constructor === fn ? this : obj, args.concat(params));
        console.log(this);
    };
    fn_.prototype = fn.prototype;
    bound.prototype = new fn_();
    return bound;
};

var z = 0;
var obj = {
    z: 1
};

function fn(x, y) {
    this.name = '听风是风';
    console.log(this.z);
    console.log(x);
    console.log(y);
};
fn.prototype.age = 26;

var bound = fn.bind_(obj, 2);
var person = new bound(3); //undefined 2 3

console.log(person.name); //听风是风
console.log(person.age); //26
person.__proto__.age = 18;
var person = new fn();
console.log(person.age); //26