理解并手写 bind() 函数

有了对call()、apply()的前提分析,相信bind()我们也可以手到擒来。

参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码:

Function.prototype.myBind = function(obj){
  // 判断调用对象是否为函数
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  // 判断绑定的对象
  obj = obj || window;
}

bind()函数与call()函数参数的格式相同,不同的是bind()返回的是一个函数。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  // 获取正确参数
  let args = [...arguments].slice(1);
  // 返回函数
  return function Fn(){};
}

使用bind()函数来对this进行绑定,可以之间在内部使用 apply() 。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  let args = [...arguments].slice(1);
  return function Fn(){
    // 直接使用apply()
    return this.apply();
    };
}

这个时候会发现,我们绑定的this是window,而不是我们想要的’this‘环境,可以使用that作为中间量。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  // 在这里借助that
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
    return that.apply();
    };
}

然后我们需要考虑apply()中传递的参数,这里我们使用数组的concat()方法,得到apply中传递的数组。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
       // 传递两个参数(绑定对象,数组)
    return that.apply(obj,args.concat(...arguments));
    };
}

最后需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
       // 根据调用方式,传入不同绑定值
    return that.apply(
      this instanceof Fn ? this : obj,       args.concat(...arguments)); }; }

最后通过一个例子,来验证是否达到bind()的功能要求。

Function.prototype.myBind = function(obj){
  if(typeof this !== 'function'){
    console.error('type error!')
  }
  obj = obj || window;
  that = this;
  let args = [...arguments].slice(1);
  return function Fn(){
    return that.apply(
      this instanceof Fn ? this : obj,
      args.concat(...arguments)
    );
  } } let dog
= {   name: '狗',   eat(food1, food2) {     console.log(this.name + '爱吃' + food1 + food2);   } } let cat = {   name: '猫', } dog.eat.bind(cat, '鱼', '肉')(); // 猫爱吃鱼肉 dog.eat.mybind(cat, '鱼', '肉')(); // 猫爱吃鱼肉

 

posted @ 2022-03-08 10:09  辉太狼`  阅读(150)  评论(0编辑  收藏  举报