JS深入基础之bind,call,与apply

144 阅读2分钟

bind

bind的主要作用是将函数绑定到某个对象上,他返回的是一个函数

bind的模拟实现

Function.prototype.bind2 = function (context) {
    //获得调用的bind的函数,用this获取
    var self = this;
    // 获取后面的一系列参数
    var args = Array.prototype.slice.call(arguments, 1);
    // 创建一个空函数作为中转,以免原型链污染
    var fNOP = function () {};

    var fBound = function () {
        // 这里的arguments是指bind返回的函数中传入的参数
        var bindArgs = Array.prototype.slice.call(arguments);
        // 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值
        // 以上面的是 demo 为例,如果改成 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改成 this ,实例会具有 habit 属性
        // 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
        return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
    }
    // 中转的空函数的原型链作为this的原型链,避免污染
    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
}

call

call是Function原型上的方法,他是用来改变绑定的this值并且执行函数的,可以这样使用它。

f.call(o)

这个意思就是在对象o的环境下来调用f函数,也就是把this挂在在了o上。

call的第一个函数固定表示需要绑定的this值,后续的参数为函数调用时的参数

f.call(o,a,b,c)

等同于在o的环境下调用f(a,b,c)

call的模拟实现

Function.prototype.call2 = function (context) {
    // 首先要获取调用call的函数,用this可以获取
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

apply

apply方法和call大致相同,不同的地方在于他的第二个函数是个数组

调用方式为

f.apply(o,[a,b,c])