apply,call,bind用js原生实现

// apply第一个参数是函数的执行环境this,第二个参数是一个数组,这个数组会自动散开成为函数的参数
Function.prototype.apply = function (x, y) {
  x = x || window
  y = y || []
  x._apply = this // this为当前函数:使函数指向x
  if (!x._apply) {  // 如果作用域x不可修改:则给它的原型添加函数
    x.constructor.prototype._apply = this
  }
  var r , j = y.length
  switch (j) {
    case 0: r = x._apply(); break
    case 1: r = x._apply(y[0]); break
    case 2: r = x._apply(y[0], y[1]); break
    case 3: r = x._apply(y[0], y[1], y[2]); break
    case 4: r = x._apply(y[0], y[1], y[2], y[3]); break
    default: r = eval('x._apply(' + y.join() + ')'); break  // eval执行效率底,所以先用js写常用的调用
  }
  try {
    delete x._apply ? x._apply : x.constructor.prototype._apply // 删除为了修改函数作用域的临时指向
  } catch (e) {}
  return r  //返回函数执行的结果
}
// call 第一个参数是函数的执行环境this,从第二个参数开始都是给函数的参数
Function.prototype.call = function () {
  let len = arguments.length - 1, x = args[0], y = []
  for (let i = 0; i < len; i++) {  // 把arguments类数组对象转化为数组 可以简写为:[].slice.apply(arguments, 1)
    y[i] = arguments[i + 1] 
  }
  return this.apply(x, y)
}
// bind 修改函数的执行环境,返回一个新函数,参数和call一样
Function.prototype.bind = function () {
  // 形成一个闭包,返回一个行函数
  let x = arguments[0], len = 0, y = [], i, j, fn = this
  for (i = 0, len = arguments.length - 1; i < len; i++) {
    y[i] = arguments[i + 1]
  }
  return function () {
    for (j = 0, len = arguments.length; j < len;) {
      y[y.length] = arguments[j++]
    }
    return fn.apply(x, y)
  }
}

猜你喜欢

转载自blog.csdn.net/zsnpromsie/article/details/80258750