【前端】模擬實現JavaScript中的apply, call函數

1.apply(thisArg, [argsArray])

在實現之前,首先看一下MDN上關於apply函數的說明:

apply() 方法調用一個具有給定this值的函數,以及作爲一個數組(或類似數組對象)提供的參數。

apply函數會將當前調用函數的this綁定在thisArgs上,我們知道,在JavaScript中,常見的函數綁定this的方法除了apply,call之外,還會在函數被當做對象的屬性調用時被這個對象綁定,
例如:

obj.func() // 執行時func中的this指向obj

根據這個思路,就容易寫出代碼了:

// 爲了讓所有的函數都能調用,需要定義在Function的原型對象上
Function.prototype.myApply = function(thisArg) {
  let fn = this;
  let args = arguments[1];
  thisArg.fn = fn; // 將函數添加到thisArgs的屬性上,通過屬性調用
  thisArg.fn(...args);
}

const obj = {
  name: 'oyy',
  age: 23,
}

const func = function(a, b, c) {
  console.log(this.name);
  console.log(a + b + c)
}

func.myApply(obj, [1, 2, 3])

上面的代碼還有些問題,如果將obj打印出來,會發現obj多了一個fn屬性,爲了不污染源對象,需要在fn調用完之後手動將其刪除

Function.prototype.myApply = function(thisArg) {
  let fn = this;
  let args = arguments[1];
  thisArg.fn = fn; // 將函數添加到thisArgs的屬性上,通過屬性調用
  thisArg.fn(...args);
  delete thisArg.fn;
}

另外,在thisArgs爲null或者undefined時,thisArg會自動替換爲指向全局對象。

Function.prototype.myApply = function(thisArgs) {
  if (!thisArgs) thisArgs = window; // 這裏指向window
  let fn = this;
  let args = arguments[1] || [];
  thisArgs.fn = fn;
  thisArgs.fn(...args);
  delete thisArgs.fn;
}

如此一來,就基本上實現了apply函數。

2.call(thisArg, arg1, arg2, …)

call() 方法使用一個指定的 this 值和單獨給出的一個或多個參數來調用一個函數。

與apply函數類似,call也能做到綁定函數的this,他們的區別在於傳參方式有些不一樣,call接受的是一個的參數列表

仍然使用上面的思路:

Function.prototype.myCall = function(thisArg) {
  if (!thisArg) thisArg = window;
  let fn = this;
  let args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push(arguments[i]);
    // args.push('arguments[' + i + ']');
  }
  thisArg.fn = fn;
  thisArg.fn(...args);
  // eval('thisArg.fn(' + args + ')');
  delete thisArg.fn;
}

上面兩個函數都使用了擴展運算符’…’,如果不用這個的話,那麼通過eval的方式傳入一個構造好的參數字符串列表也可以達到一樣的效果(看註釋部分)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章