一、bind方法的作用?

bind() 方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定为bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。 --MDN

简单说,bindcall/apply类似都也是改变this的指向。但是bind并不会立即执行函数,而是返回一个绑定了this的新函数,且新函数的this无法再次被修改。
举个例子吧:

let obj = {
	num:1,
	add : function (a,b) {
		return a+b+this.num;
	}
}
console.log(obj.add(1,2));//4
let plus = obj.add;
// 原因:this.num在当前作用域内不存在,this指向window
console.log(plus(1,2));//NaN
// 使用call/apply改变this的指向
console.log(plus.call(obj, 1,2)); //4
console.log(plus.apply(obj, [1, 2]));//4
//bind返回一个新函数
let res = plus.bind(obj,1,2);
console.log(res());//4

二、bind方法实现

先通过一个例子来看一下bind都做了什么

var obj = {name:"Smiley"};
var greeting = function(str, lang){
    this.value = 'greetingValue';
    console.log("Welcome "+this.name+" to "+str+" in "+lang);
};
var objGreeting = greeting.bind(obj, 'the world'); 
objGreeting('JS')
  1. bind改变了greeting当中this的指向,使得this指向了obj,因此,this.name的内容是Smiley。最后,bind会返回一个函数。
  2. 我们可以在调用bind的时候,就可以开始给greeting传递参数。上面的例子当中,我们把’the world’作为greeting的第一个参数。
  3. 我们在调用objGreeting这个函数的时候,再传入剩余的参数。上面的例子中,第二个参数是’JS’作为第二个参数lang。
  4. 这个是MDN中提到的:“bind()函数会创建一个新绑定函数(bound function,BF)。绑定函数也可以使用new运算符构造,提供的this值会被忽略,但前置参数仍会提供给模拟函数”。有点晦涩,这也是bind实现中最复杂的一步,使用new关键字这种情况我们一会儿再分析。

接下来我们实现bind:

Function.prototype._bind = function(oThis){
    if(typeof this !== 'function'){
      throw new TypeError('被绑定的对象需要是函数')}
    const self = this// 将类数组对象转换成数组并截取
    const args = [].slice.call(arguments, 1);
    let func = function(){}let fBound = function(){ 
    // instanceof用来检测某个实例对象的原型链上是否存在这个构造函数的prototype属性,this instanceof func === true时,
    //说明返回的fBound被当做new的构造函数调用,此时this=fBound(){},否则this=window, 
    //如果是的话使用新创建的this代替硬绑定的this
      return self.apply(this instanceof func ? this : oThis, args.concat([].slice.call(arguments)))}
    //维护原型关系
    if(this.prototype){
      func.prototype = this.prototype;
    }
    //使fBound.prototype是func的实例,返回的fBound若作为new的构造函数,新对象的__proto__就是func的实例
    fBound.prototype = new func()return fBound;
  }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐