JavaScript系列之手写bind

149 阅读2分钟

Function.prototype.bind()

我们需要先了解这个函数是做什么的,bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。 由此我们可以首先得出 bind 函数的两个特点:

  1. 返回一个函数;
  2. 可以传入参数;

我们由此来模拟一个bind的实现

var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

// 返回了一个函数
var bindFoo = bar.bind(foo); 

bindFoo(); // 1

现在我们来仿照这个需求来手写一下bind方法 需要把方法绑定在原型上

1.1 没有参数的情况下

var foo = {
    value: 1
};

function bar() {
    console.log(this.value);

}


Function.prototype.bind2 = function (context) {
    var self = this;  //self的this指向是指向调用bind2这个方法的函数的,也就是外部函数

    // 虑到绑定函数可能是有返回值的,加上return
    return function () {
        return self.apply(context);
        /* 
        外部函数.apply(context) 也就是说 
        this的指向指向了context 
        并且执行了外部函数
        满足了我们的需求会调用新的函数并且改变this指向 使它指向第一个参数
        */  
    }

}
bar.bind2(foo)()    // 1    //因为他返回的时候是一个函数所以需要我们调用一次


1.2 在有参数的情况

var foo = {
    value: 1
};

function bar(name, age) {
    console.log(this.value);
    console.log(name);
    console.log(age);

}


Function.prototype.bind2 = function (context) {
    var self = this;  //self的this指向是指向调用bind2这个方法的函数的,也就是外部函数
  // 获取bind2函数从第二个参数到最后一个参数
  var args = Array.prototype.slice.call(arguments, 1);  
  // 这段代码的意思是指给原型对象绑定数据将this指向指向为arguments数组并且执行slice函数 从索引为1时候开始截取
   
  // 虑到绑定函数可能是有返回值的,加上return
    return function () {
        // 这个时候的arguments是指bind返回的函数传入的参数
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(context, args.concat(bindArgs));
    }

}
bar.bind2(foo,'ss',123)()  //1,ss,123

这就是关于手写bind的所有情况啦