本文详细介绍JavaScript中Function.prototype.bind()方法的作用与用法。通过对比传统self=this写法,展示bind如何更优雅地绑定this上下文。文章包含基础使用示例、内部实现原理剖析,以及针对IE8及以下浏览器的Polyfill兼容代码,帮助开发者解决旧版浏览器不支持该API的问题。
Function.prototype.bind() 基础用法与优势
过去,开发者常通过设置 self=this 或 that=this 来维持上下文引用。虽然这种方法可行,但使用 Function.prototype.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();在上述示例中,为了保持 myObj 的执行上下文,我们声明了一个变量 that=this。这种方式虽然有效,但相比直接使用 Function.prototype.bind(),代码结构略显冗余。改进后的写法更加整洁:
代码如下:
render: function () {
this.getAsyncData(function () {
this.specialFunction();
this.anotherSpecialFunction();
}.bind(this));
}
bind 方法内部实现原理
当调用 .bind() 时,它会创建一个新的函数,并将指定的 this 值传递给该新函数。其内部实现逻辑大致如下:
代码如下:
Function.prototype.bind = function (scope) {
var fn = this;
return function () {
return fn.apply(scope);
};
}bind 方法使用示例
再看一个使用 Function.prototype.bind() 的基础示例:
代码如下:
var foo = {
x: 3
};
var bar = function(){
console.log(this.x);
};
bar(); // 输出 undefined
var boundFunc = bar.bind(foo);
boundFunc(); // 输出 3IE8及以下浏览器的兼容方案
是否十分便捷!然而遗憾的是,IE8及更低版本的IE浏览器不支持Function.prototype.bind()。兼容的浏览器包括Chrome 7+、Firefox 4.0+、IE 9+、Opera 11.60+以及Safari 5.1.4+。尽管IE 8/7/6等旧版浏览器不支持,Mozilla开发组仍为老版本IE编写了一个功能相似的函数,具体代码如下:
代码如下:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// 最接近 ECMAScript 5 内部 IsCallable 函数的实现
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}