手写bind函数

8/3/2021 bind函数

# 手写bind函数

bind是function原型对象上的函数,即每个函数都可以调用bind函数。其作用是用于创建一个新函数。

  1. # bind函数概念

bind是function原型对象上的函数,即每个函数都可以调用bind函数。其作用是用于创建一个新函数A。在bind被调用时,这个新函数A的this被指定为bind()的第一个参数,而bind()传入的其余的参数将作为新函数的参数,供调用时使用。

this.x = 9;    // 在浏览器中,this 指向全局的 "window" 对象
var module = {
  x: 81,
  getX: function() { return this.x; }
};

var retrieveX = module.getX;
retrieveX(); // 9
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
module.getX(); // 81
//bind函数将this指向module
1
2
3
4
5
6
7
8
9
10
11
12
  1. # 手写bind函数

手写bind之前先看看bind函数的使用逻辑:

function foo() {
    this.b = 100;
    return this.a;
}
let func = foo.bind({a: 1});
func(); // 1
new func(); // foo { b: 100 }
1
2
3
4
5
6
7
  • 作用对象首先是个函数
  • 第一个参数作为新函数的this,剩下参数作为新函数的参数
  • 当new 一个新的新函数的实例的时候,新创建的实例对象要绑到当前this上,新实例的原型对象要指向当前函数的原型
Function.prototype.myBind = function(oThis){
    // 作用对象首先是个函数
    if(typeof this !== 'function') {
        throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    // 第一个参数作为新函数的this
    let aArgs = Array.prototype.slice.call(arguments, 1);
    let fToBind = this;
    
    let fNOP = function() {};
    let fBound = function(){
        return fToBind.apply(
            fNOP.prototype.isPrototypeOf(this) ? this:oThis,  // 如果是直接调用新函数,this指向第一个参数;如果是new的新函数,this指向新创建的实例对象,且新实例的原型对象要指向当前函数fNOP的原型
            aArgs.concat(Array.prototype.slice.call(arguments))); // 剩下参数作为新函数的参数
    }
    if(this.prototype) {
        fNOP.prototype = this.prototype; 
    }
    fBound.prototype = new fNOP(); //返回新函数的原型对象是调用函数的一个实例,这样new的新对象也能够获取调用函数的属性和方法

    return fBound;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

查看结果

function foo() {
    this.b = 100;
    return this.a;
}
let func = foo.myBind({a: 1});
func(); // 1
let nf = new func(); // foo { b: 100 }
nf.__proto__ // foo {}
1
2
3
4
5
6
7
8