call,apply,bind區別與實現

區別: 指定this,call和apply執行函數,bind不執行

callapplybind都是爲了解決this的指向,callapply都會執行函數,而bind只是綁定this不執行函數。callapply接受參數方式不一樣,除了第一個參數都是指定thiscall接受一個參數列表,apply 只接受一個參數數組。

var obj = {
  value: 1
}
function foo(a, b) {
  console.log(a, b)
  console.log(this.value)
}
foo.call(obj, 1, 2)
foo.apply(obj, [1, 2])

// bind 只綁定
foo.bind(obj, 1, 2)

模擬實現call,apply,bind

實現思路

  • 不傳入第一個參數,則默認爲window
  • 改變this指向,讓新的對象可以執行該函數。=》給新的對象添加一個函數,執行之後刪除

call的實現

Function.prototype.myCall = function (context) {
  var context = context || window;  // 傳入的新對象
  // 給新對象添加一個屬性(方法)
  context.fn = this; // this 指向的是調用myCall方法的函數
  // 取出剩餘參數
  var args = [...arguments].slice(1);
  var result = context.fn(...args); // 調用context.fn實則調用myCall方法的函數,但函數this指向了context
  delete context.fn;
  return result
}

apply的實現

call方法實現中參數傳遞方式改爲數組形式

Function.prototype.myApply = function (context) {
  var context = context || window;  // 傳入的新對象
  // 給新對象添加一個屬性(方法)
  context.fn = this; // this 指向的是調用myCall方法的函數
  // 剩餘參數 數組形式
  var result;
  if(arguments[1]) {
    result = context.fn(...arguments);
  } else {
    result = context.fn();
  }
  delete context.fn;
  return result
}

bind的實現

this指向,返回一個函數

Function.prototype.myBind = function (context) {
  var context = context || window;
  var _this = this; 
  var args = [...arguments].slice(1);
  return function () {
    _this.apply(context, args.concat(...arguments))
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章