# new/call/bind/apply/interface 手写

# call

// 无参数 基础版本
function myCall(context) {
  context.fn = this // 给传入的对象赋值当期调用的函数
  const res = context.fn() // 对这个对象执行函数
  delete context.fn // 删掉当前函数
  return res // 返回调用的值
}

// 有参数 es6版本
function myCall(contextObj) {
  const context = contextObj || window
  context.fn = this // 给传入的对象赋值当期调用的函数
  const args = [...arguments].slice(1)
  const res = context.fn(...args) // 对这个对象执行函数
  delete context.fn // 删掉当前函数
  return res // 返回调用的值
}
// es5版本
function myCall(context) {
  var context = context || window
  context.fn = this

  var args = []
  for (var i = 1, len = arguments.length; i < len; i++) {
    args.push('arguments[' + i + ']')
  }

  var result = eval('context.fn(' + args + ')')

  delete context.fn
  return result
}

Function.prototype.myCall = myCall

# apply

// 有参数 es6版本
function myApply(contextObj, arr) {
  const context = contextObj || window
  context.fn = this // 给传入的对象赋值当期调用的函数
  let res
  if (arr) {
    res = context.fn(arr)
  } else {
    res = context.fn(arr)
  }
  // 对这个对象执行函数
  delete context.fn // 删掉当前函数
  return res // 返回调用的值
}
// es5版本
function myCall(context) {
  var context = context || window
  context.fn = this

  var result
  var args = []

  if (arr) {
    for (var i = 1, len = arguments.length; i < len; i++) {
      args.push("arguments[' + i + ']")
    }

    result = eval('context.fn(' + args + ')')
  } else {
    result = context.fn()
  }

  delete context.fn
  return result
}

Function.prototype.myCall = myApply

# bind

# new

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一

// 第二版的代码
function objectFactory() {
  // 创建一个新的对象
  var obj = new Object()
  // 取出参数的第一项 构造函数
  Constructor = [].shift.call(arguments)
  // 将构造函数的原型变为新对象的原型 (每个函数都有prototype 指向原型对象)
  obj.__proto__ = Constructor.prototype
  // 调用函数改变this的为新的对象
  var ret = Constructor.apply(obj, arguments)
  // 当实际构造函数有返回值为对象时 返回该对象 否则返回新对象
  return typeof ret === 'object' ? ret : obj
}
上次更新: 3/17/2022, 9:06:11 PM