JavaScript Function.prototype.bind 详解与兼容实现

作者:小括号

时间:2026-10-21

浏览:423

本文详细解析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值被忽略,同事调用的参数被提供给模拟函数。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章