欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

apply,call,bind用js原生实现(代码实例)

程序员文章站 2022-08-09 19:01:41
apply,call,bind用js原生实现(代码实例) // apply第一个参数是函数的执行环境this,第二个参数是一个数组,这个数组会自动散开成为函数的参数 function.prot...

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)
  }
}