JavaScript Function.prototype.bind 详解与兼容实现
本文详细解析JavaScript中Function.prototype.bind方法的作用、语法及参数含义。通过对比传统this缓存方案,展示bind在解决回调函数this丢失问题上的优势,并提供IE8及以下版本的polyfill兼容代码,帮助开发者掌握绑定函数的创建与使用。
Function.prototype.bind 概述
Function.prototype.bind机制解析
bind()方法生成一个新的绑定函数。调用该绑定函数时,其内部this指向创建时传入的第一个参数,后续参数由bind()传入及运行时传入的参数按序组合,用于调用原函数。
bind 方法的应用场景
实际开发中常遇到以下场景:
var name = "pig";
function Person(name){
this.name = name;
this.getName = function(){
setTimeout(function(){
console.log("Hello,my name is "+this.name);
},100);
}
}
var weiqi = new Person("卫旗");
weiqi.getName();
//Hello,my name is pig
此时输出this.name为pig,因为this指向在函数运行时确定而非定义时确定。由于setTimeout在全局环境下执行,导致this指向window。
以往解决此问题的常见方式是缓存this,例如:
var name = "pig";
function Person(name){
this.name = name;
this.getName = function(){
//在这里缓存一个this
var self = this;
setTimeout(function(){
//在这里是有缓存this的self
console.log("Hello,my name is "+self.name);
},100);
}
}
var weiqi = new Person("卫旗");
weiqi.getName();
//Hello,my name is 卫旗
该方法有效且便捷,因为它允许setTimeout函数内部访问Person的上下文。
现在有更优解,即使用bind()函数,上述示例可更新为:
var name = "pig";
function Person(name){
this.name = name;
this.getName = function(){
setTimeout(function(){
console.log("Hello,my name is "+this.name);
}.bind(this),100);
//注意上面这一行,添加了bind(this)
}
}
var weiqi = new Person("卫旗");
weiqi.getName();
//Hello,my name is 卫旗
bind()的最简用法是创建一个无论何种调用方式都拥有相同this值的函数。JavaScript新手常犯的错误是将对象方法提取后调用,期望this仍指向原对象(如在回调中)。若不特殊处理,通常会丢失原对象引用。通过原函数和原对象创建绑定函数,可优雅解决此问题:
//定义全局变量x
var x = "window";
//在module内部定义x
var module = {
x:"module",
getX:function(){
console.log(this.x);
}
}
module.getX();
//返回module,因为在module内部调用getX()
var getX = module.getX;
getX();
//返回window,因为这个getX()是在全局作用域中调用的
//绑定getX()并将this值设为module
var boundGetX = getX.bind(module);
boundGetX();
//返回module,绑定以后this值始终为module
浏览器兼容性与 polyfill 实现
浏览器兼容性:
| Browser | Version support |
|---|---|
| Chrome | 7 |
| FireFox(Gecko) | 4.0(2) |
| Internet Explorer | 9 |
| Opera | 11.60 |
| Safari | 5.14 |
遗憾的是,Function.prototype.bind在IE8及以下版本不支持,若无备选方案可能导致运行时错误。bind函数于ECMA-262第五版引入,可能无法在所有浏览器运行。可在脚本中加入如下代码以兼容不支持bind()的浏览器。
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
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 || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
语法与参数详解
语法
fun.bind(thisArg[, arg1[, arg2[, …]]])
参数
thisArg,绑定函数被调用时,该参数作为原函数运行时的this指向;使用new操作符调用绑定函数时,该参数无效。
arg1, arg2, …,绑定函数被调用时,这些参数与绑定函数本身的参数按序组合,作为原函数运行时的参数。
描述
bind()函数创建一个新的绑定函数,拥有相同的函数体(ECMAScript 5规范内置Call属性)。当该函数被调用时,this值绑定到bind()的第一个参数,且不可重写。绑定函数被调用时,bind()也接受预设参数提供给原函数。绑定函数也可使用new操作符创建对象:行为如同将原函数作为构造器。提供的this值被忽略,同事调用的参数被提供给模拟函数。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
