this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象
// 新手可能会被全局的x变量和module里的属性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
var o={
f: function () {
var self=this;
var fff=function() {
console.log(this.value); //此时 this 指向的是全局作用域 global/window,因此需要使用 self 指向对象o
}.bind(this);
fff();
},
value: "Hello World!"
};
o.f(); // Hello World!
再看一个例子:
function f(y,z){
return this.x+y+z;
}
var m=f.bind({x:1},2);
console.log(m(3)); // 6
这是因为 bind()
方法会把传入它的第一个实参绑定给f函数体内的 this
,从第二个实参起,将依此传递给原始函数,因此 {x:1}
传递给this
,2
传递给形参y
,m(3)
调用时的3
传递给形参z
。
其实这个例子 f()
函数能够处理部分参数,分步计算 ( bind()
时处理了参数x
,和参数y
,调用 m(3)
时处理了参数z
)的过程其实是一个典型的Curry过程(Currying)。
bind()背后的简单原理
那么bind函数背后做了什么呢? 我们可以用以下代码来模拟:
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()
后,我们创建了一个新的函数,通过调用 apply
将 this
设置成 foo
, OK,现在应该比较清晰了,但实际 bind()
的实现远比上面的复杂,如上面提到的 curry化过程等,上面只是主要原理便于学习理解 bind()
函数。