JS-手动实现bind、call方法

2019-12-27  本文已影响0人  葶寳寳

实现bind方法

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

1.首先bind方法会返回一个新的函数。在返回的新函数中调用call或apply方法来改变this指向。

Function.prototype.bind = function(obj) {
   let self = this;
   let args = [];
   for(let i = 0; i < arguments.length; i++){
       args[i] = arguments[i];
   }
   return function () {
        return self.call(obj, ...args.splice(1), ...arguments);
   }
}

2.当我们将bind后的函数当构造函数使用时,this绑定应该失效。

const a = 1;
let obj  = {
   a: 2
}

function func() {
   thia.name = 'ltt';
   console.log(this.a);
}

let f = func.bind(obj);
let o = new f();  // 2 ,实际应该输出underfind

new一个构造函数时,先会创建一个构造函数(f)的子类,然后返回对象o。当构造函数有返回值是对象或数组的时候,就会返回对象/数组;当有其他类型的返回值时,返回对象o。

let o = create Object();
o.__proto__ = f.prototype;
f.call(o);

return o;

所以,我们接着改造我们的bind方法。关键点是什么时候我们应该让this指向失效?也就是得判断什么时候把bind绑定函数当构造函数来用。

上边也提到了,new一个构造函数的时候,先创建一个它的子类o,然后调用call方法。call方法的执行的本质是将该构造函数f作为第一个参数o的方法,然后调用o.f(),使f函数内部的this指向o。而这里的f方法,就是bind中的返回的b方法。所以我们就可以用this来判断是否为o的实例,若是,说明bind方法被用来当构造函数使用的。

Function.prototype.bind = function(obj) {
   let self = this;
   let args = [];
   for(let i = 0; i < arguments.length; i++){
       args[i] = arguments[i];
   }
   function b() {
        return self.call(this instanceof b ? this : obj, ...args.splice(1), ...arguments);
   }
   return b;
}

至此,bind函数就大致实现了。

实现call方法

Function.prototype.call = function(obj){
  obj.func = this;
  var res = obj.func(arguments);
  
  delete obj.func;
  
  return res;
}
上一篇下一篇

猜你喜欢

热点阅读