浅析 JavaScript 中的 Function.prototype.bind() 方法

Function.prototype.bind()方法

bind() 方法的主要做用就是将函数绑定至某个对象,bind() 方法会建立一个函数,函数体内this对象的值会被绑定到传入bind() 函数的值。app

例如,在 f() 函数上调用 bind() 方法并传入参数 obj ,即 f.bind(obj) ,这将返回一个新函数, 新函数会把原始的函数 f() 当作 obj 的方法来调用,就像 obj.f() 似的,固然这时 f() 函数中的 this 对象指向的是 obj函数

简单使用情形一

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(self.value);  //此时 this 指向的是全局做用域 global/window,所以须要使用 self 指向对象o
        };
        fff();
    },
    value: "Hello World!"
};
o.f(); // Hello World!

上例是咱们经常使用了 保持 this 上下文的方法,把 this 赋值给了中间变量 self,这样在内部嵌套的函数中可以使用 self 访问到对象o,不然仍使用 this.value,内部嵌套函数的this此时指向的是全局做用域,最后的输出将会是 undefined,代码以下:学习

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(this.value); 
        };
        fff();
    },
    value: "Hello World!"
};
o.f(); // undefined

可是,若是咱们使用 bind()函数,将fff函数的绑定在对象o中,即将fff()函数内部的 this 对象绑定为对象 o,那么能够碰见此时 this.value 是存在的。代码以下:测试

var o={
    f: function () {
        var self=this;
        var fff=function() {
            console.log(this.value); // bind(this) 中 this 指向的是o,这里也可直接写成 bind(o)
        }.bind(this);
        fff();
    },
    value: "Hello World!"
};
o.f(); // Hello World!

更广泛的使用情形

再看一个例子:this

function f(y,z){
    return this.x+y+z;
}
var m=f.bind({x:1},2); 
console.log(m(3));  // 6

最后将输出 6prototype

这是由于 bind()方法会把传入它的第一个实参绑定给f函数体内的 this,从第二个实参起,将依此传递给原始函数,所以 {x:1}传递给this ,2传递给形参ym(3) 调用时的3 传递给形参zcode

其实这个例子 f() 函数可以处理部分参数,分步计算 ( bind() 时处理了参数x,和参数y,调用 m(3)时处理了参数z )的过程实际上是一个典型的Curry过程(Currying)。对象

bind()背后的简单原理

那么bind函数背后作了什么呢? 咱们能够用如下代码来模拟:ip

Function.prototype.testBind = function (scope) {
    var fn = this;                                // this 指向的是调用testBind方法的一个函数
    return function () {
        return fn.apply(scope, arguments);
    }
};

下面是测试的例子:作用域

var foo = {x: "Foo "};
var bar = function (str) {
    console.log(this.x+(arguments.length===0?'':str));
};

bar();                                   // undefined

var testBindBar = bar.testBind(foo);     // 绑定 foo
testBindBar("Bar!");                     // Foo Bar!

当调用 testBind() 后,咱们建立了一个新的函数,经过调用 applythis 设置成 foo, OK,如今应该比较清晰了,但实际 bind() 的实现远比上面的复杂,如上面提到的 curry化过程等,上面只是主要原理便于学习理解 bind() 函数。

参考资料: Javascript权威指南

相关文章
相关标签/搜索