bind,call,apply模擬實現

炸雞啤酒不可負發表於2020-09-17

首先,三者第一個引數都為this指向

區別

bind返回的是一個函式體

call和apply會直接執行,但是call引數需要一個一個進行傳遞,apply的第二個引數是一個陣列

實現

bind

簡單實現

Function.prototype.myBind = function(context){
  self = this;  //儲存this,即呼叫bind方法的目標函式
  return function(){      return self.applay(context, [...arguments]);
  };
};

考慮到函式柯里化的實現

Function.prototype.myBind = function(context){  // 使用閉包存下初始引數
  var args = Array.prototype.slice.call(arguments, 1),
  self = this;  return function() {        // 再次呼叫時
      var innerArgs = Array.prototype.slice.call(arguments);      var finalArgs = args.concat(innerArgs);      return self.apply(context,finalArgs);
  };
};

考慮建構函式的實現

Function.prototype.myBind = function(context){  // 判斷是否為函式
  if(typeof this !== 'function') {    throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  }  var args = Array.prototype.slice(arguments, 1);
  self = this;
  bound = function() {      var innerArgs = Array.prototype.slice.call(arguments);      var finalArgs = args.concat(innerArgs);      // 判斷this,如果是,則傳遞this即例項化的物件。
      return self.apply((this instanceof F ? this : context), finalArgs);
  };  // 處理原型鏈
  let F = function(){};
  F.prototype = self.prototype;
  bound.prototype = new F();
  retrun bound;
};

call

思路

// 要實現這個效果var foo ={
  value:1}function bar(){
  console.log(this.value)
}
bar.call(foo);//1// 相當於做如下事情var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
};
foo.bar(); // 1

實現

Function.Prototype.myCall = function(context) {  // this 引數可以傳 null,當為 null 的時候,視為指向 window
  var context = context || window;
    context.fn = this;  // 對引數進行處理
    var args = [];  for(var i = 1, len = arguments.length; i < len; i++) {
      args.push(arguments[i]);
  }
  let result = arguments.length>0 ? context.fn(...args) : context.fn();  delete context.fn;  return result;
}

apply

Function.Prototype.myApply = function(context, arr) {  // this 引數可以傳 null,當為 null 的時候,視為指向 window
  var context = context || window;
    context.fn = this;
  let result = arr.length>0 ? context.fn(...arr) : context.fn();  delete context.fn;  return result;
}





轉自https://www.cnblogs.com/suihang/p/13661021.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69983799/viewspace-2722001/,如需轉載,請註明出處,否則將追究法律責任。

相關文章