call apply 原生實現

call apply 原生實現

call() 和 apply() 類似於借用,相當於 A 對象內部有了 B 對象的方法,實質是函數在運行時指定 this 值,打破瞭解析器在函數調用時創建執行環境時this綁定的規則。

call 源碼

例子:

const val = {
  a:1
}
function add(b,c){
  return this.a + b + c
}
console.log(add.call(val,2,3))	//6

相當於:

1.給 val 對象增加方法 add

2.執行 val 對象的方法 add

3.刪除 add 方法

val.add = function(b,c){...}
console.log(val.add(2,3))	//6
delete val.add

call 原生實現:

Function.prototype.callFunc = function(context){
  var context = context || window		//undefined 時 this 綁定在全局
  context.fn = this
  var args = []
  for(var i = 1, len = arguments.length; i < len; i++){
    args.push('arguments[' + i + ']')	//i 爲1,除去第一個參數
  }
  var result = eval('context.fn(' + args + ')')	//eval 執行字符串內容
  // es6 的 rest 寫法: var result = context.fn(...args)
  delete context.fn
  return result
}

es6 的 rest 寫法:

Function.prototype.callFunc = function(context){
  var context = context || window		//undefined 時 this 綁定在全局
  context.fn = this
  var args = []
  for(var i = 1, len = arguments.length; i < len; i++){
    args.push(arguments[i])	//i 爲1,除去第一個參數
  }
   var result = context.fn(...args)
  delete context.fn
  return result
}

通過在第一個參數 context 的屬性中存儲了調用 callFunc 函數的方法,然後再在 context 的執行環境中調用該屬性(即執行該方法)

apply 源碼

和 call 發生的過程一樣,不過需要判斷第二個參數是否是數組

apply 原生實現:

Function.prototype.applyFn = function(context,arr){
  var context = context || window
  context.fn = this	
  var result
  if(!arr){	不輸入第二個參數時
    result = context.fn();
  }else{
    if(!(arr instanceof Array))
      throw new Error('params must be array');
    else
      result = eval('context.fn('+arr+')');
      // es6 的 rest 寫法: var result = context.fn(...args)
  }
  delete context.fn
  return result
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章