Javascript中bind实现

MDN中bind是这样定义的:
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

由此我们可以看出bind 函数的两个特点:
1. 绑定this,返回一个新函数,便于稍后调用;
2. 可以传入参数 (可以预传参,只需要传入剩下的参数)

看个bind应用的例子:

var person = {
    name: 'nuan'
}

function sayName(prefix, suffix){
    console.log(prefix + this.name + suffix)  // Hello, nuan???
}

var newSayName = sayName.bind(person,'Hello, ')
newSayName('???')

下面从bind函数的两个特点进行实现:

为了满足第一个返回一个新函数的特点,下面是个简化版的bind实现:

Function.prototype.bind = function(context){
    var self = this;    //保存原函数
    return function(){      //返回一个新的函数
        return self.apply(context, arguments);      //执行新的函数的时候,会把之前传入的context当做新函数体内的this
    }
}

var obj = {
    name: 'sven'
}
var func = function(){
    console.log(this.name);    //sven
}.bind(obj);

func();   

为了满足第二个bind函数可以预传参,只需要传入剩下的参数的特点,最终实现如下:

Function.prototype.bind = function () {
  var self = this, //保存原函数
      context = [].shift.call(arguments), //需要绑定的this上下文
      args = [].slice.call(arguments); //剩余的参数转为数组
  return function(){ //返回一个新的函数
      return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
      //执行新的函数的时候,会把之前传入的context当做新函数体内的this
      //并且组合两次分别传入的参数,作为新函数的参数
  }
}

var obj = {
  name: 'sven'
}
var func = function(a, b, c, d) {
  console.log(this.name);       //sven
  console.log([a, b, c, d]);    //[1, 2, 3, 4]
}.bind(obj, 1, 2);

func(3, 4); 

参考阅读

  1. JavaScript设计模式与开发实践–曾探著
  2. bind
  3. bind函数的实现
### JavaScript中 `bind` 方法的使用说明 `bind()` 方法用于创建一个新的函数实例,在该新函数被调用时,会将其 `this` 关键字设置为指定的对象。这使得我们可以控制函数执行时的上下文环境[^1]。 #### 基本语法 以下是 `bind()` 的基本语法结构: ```javascript function.bind(thisArg, arg1, arg2, ...); ``` - **`thisArg`**: 调用绑定函数时作为其 `this` 值传递给目标函数的对象。 - **`arg1, arg2, ...`**: 可选参数列表,这些参数会在最终调用绑定函数时置到目标函数的参数前面。 #### 特点 1. 返回的新函数不会立即执行,而是等待显式的调用。 2. 绑定后的函数即使通过其他方式调用(如事件处理程序),它的 `this` 依然指向最初绑定的对象[^3]。 --- ### 示例代码 以下是一些常见的 `bind()` 使用场景: #### 场景一:改变函数内部的 `this` 指向 假设有一个对象和一个独立定义的函数,我们希望让这个函数运行时的 `this` 指向某个特定对象。 ```javascript const person = { name: 'Alice', greet: function(greeting) { console.log(`${greeting}, my name is ${this.name}`); } }; // 创建了一个新的函数,绑定了 this 到 person 对象 const boundGreet = person.greet.bind(person); boundGreet('Hello'); // 输出: Hello, my name is Alice ``` 此处,尽管 `boundGreet` 是单独的一个变量,但由于绑定了 `person` 对象,因此在调用时仍然可以访问 `person` 上的属性。 --- #### 场景二:部分应用 (Partial Application) 除了修改 `this` 外,还可以提前设定一些固定参数。 ```javascript function multiply(a, b) { return a * b; } // 设第一个参数为 5 const multiplyByFive = multiply.bind(null, 5); console.log(multiplyByFive(10)); // 输出: 50 ``` 这里需要注意的是,当不需要更改 `this` 的值时,可以用 `null` 或者 `undefined` 来占位[^2]。 --- #### 场景三:结合回调函数使用 在异步编程或者 DOM 事件监听器中,经常需要用到 `bind()` 来确保正确的上下文。 ```javascript const button = document.querySelector('#myButton'); button.addEventListener('click', function(event) { console.log(`The button was clicked by ${this.id}`); }.bind(button)); ``` 在这个例子中,如果没有使用 `.bind(button)`,那么默认情况下 `this` 将指向触发点击事件的实际元素而不是按钮本身。 --- ### 实现原理 下面展示如何手写模拟实现一个简单的版本: ```javascript Function.prototype.myBind = function(context) { const fn = this; // 当前函数引用 const args = Array.from(arguments).slice(1); // 获取额外传入的参数 return function(...newArgs){ return fn.apply(context, [...args, ...newArgs]); }; }; ``` 此自定义版实现了基础功能并支持参数合并操作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值