js高級進階——手動實現call()函數

// 首先看下原生的js的call()
var obj = {
  name: 'Nicholas S.Zakas',
  age: 41,
  from: 'America',
  getName: function (prefix) {
    // console.log(prefix + this.name)
    return prefix + this.name
  }
}

var obj2 = {
  name: 'Evan You',
  age: '35',
  from: 'China'
}

console.log(obj.getName.call(obj2, 'hello, everyone, i am '))
// hello, everyone, i am Evan You

// call()做了什麼?
// 1、將調用call的函數的this指向call函數的第一個參數
// 2、將call()第一個參數後的參數作爲調用call函數的形參
Function.prototype._call = function (context) {
  var result
  var args = [].slice.apply(arguments, [1])
  context.fn = this
  result = context.fn(...args)
  delete context.fn
  return result
}

// 不使用call函數的實現
Function.prototype._newCall = function (context) {
  var args = []
  var result
  for (var i = 1; i < arguments.length; i++) {
    args.push('arguments[' + i + ']')
  }
  context.fn = this
  result = eval('context.fn(' + args + ')')
  delete context.fn
  return result
}

console.log(obj.getName._newCall(obj2, 'hello, everyone, i am '));
// hello, everyone, i am Evan You

// ECMAScript6 的實現
Function.prototype._es6Call = function (context, ...args) {
  var result
  context.fn = this
  result = context.fn(...args)
  delete context.fn
  return result
}

console.log(obj.getName._es6Call(obj2, 'hello, everyone, i am '));
 // hello, everyone, i am Evan You

 

2020.05.15 修正函數調用call會有返回值

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