初学JavaScript
时,你可能最不想关心的就是函数绑定。不过当遇到一个经典问题,如何在另外一个函数中保持this
指针。这个时候,你会明白Function.prototype.bind()
是一个解决办法。
第一次遇到这个问题的时候,你可能更倾向于通过一个变量来持有this,这样即使更换了函数的context(上下文),依然可以成功调用函数。许多人会用self,_this,甚至context作为这个变量名,我常见的是that。这个方式没有问题,不过相比较bind更赞。
我们到底要解决什么问题?
下面一段代码
var myObj = {
specialFunction: function () {
},
anotherSpecialFunction: function () {
},
getAsyncData: function (cb) {
cb();
},
render: function () {
var that = this;
this.getAsyncData(function () {
that.specialFunction();
that.anotherSpecialFunction();
});
}
};
myObj.render();
上面的代码是正确的,如果直接使用this.specialFunction
,函数已经失去了当前上下文,然后就会收到以下错误
Uncaught TypeError: Object [object global] has no method 'specialFunction'
注意:严格模式,此种情况上下文为undefined
为了能让specialFunction正常调用,我们需要保证它在被调用时候context是指向的myObj对象。使用that.specialFunction()能让我们持有context并正确调用函数。
修改部分代码:
render: function () {
this.getAsyncData(function () {
this.specialFunction();
this.anotherSpecialFunction();
}.bind(this));
}
刚刚做了什么
bind()会返回一个新的函数。使用时,可以把this作为参数传进去,那么返回的新函数就和this绑定在一起了。在结合上面的代码,我们传了this(就是myObj)和函数绑定在一起,这是我们希望的context。然后等到函数执行的时候,this就会指向myObj对象。
如果对bind内部实现有兴趣,可以看下下面的代码。
Function.prototype.bind = function (scope) {
var fn = this;
return function () {
return fn.apply(scope);
};
}
观察apply的函数定义,fun.apply(thisArg, [argsArray])
它的第一个参数就是函数的上下文。
下面有一个非常简单的bind使用例子
var foo = {
x: 3
}
var bar = function(){
console.log(this.x);
}
bar(); // undefined
var boundFunc = bar.bind(foo);
boundFunc(); // 3
如果不调用bind,bar的context是全局的(global scope),也就是this指针指向的window。绑定完后,bar的this指针指向foo。
浏览器支持
浏览器 | 支持版本 |
---|---|
Chrome | 7 |
Firefox (Gecko) | 4.0(2) |
Firefox (Gecko) | 4.0(2) |
Internet Explorer | 9 |
Opera | 11.60 |
Safari | 5.1.4 |
最后
我没有逐字逐句进行翻译,其中有些内容我按照自己的理解进行了略微修改,还有些内容我直接跳过。欢迎阅读原文。
https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/