Skip to content
本页目录

函数方法

特别说明下,当通过下面三个方法(任意一个)调用箭头函数时,由于箭头函数自身没有this,故第一个参数会被忽略掉(即只能传参,不能绑定this)。
更具体的例子可前往MDN查看,传送门通过callapplybind调用

Function#call()

JavaScript
if (!Function.prototype.call) {
  Function.prototype.call = function (ctx) {
    if (typeof this !== 'function') {
      throw new TypeError('call方法的调用标识符必须为函数!')
    }
    var ctx = ctx || window, args = [], ret
    ctx.fn = this
    for (var i = 1, len = arguments.length; i < len; i++) {
      args.push('arguments[' + i + ']')
    }
    ret = eval('ctx.fn(' + args + ')')
    delete ctx.fn
    return ret
  }
}

关于eval()函数:eval()函数可计算某个字符串,并执行其中的JavaScript代码。

替代方案
JavaScript
if (!Function.prototype.call) {
  Function.prototype.call = function (ctx) {
    if (typeof this !== 'function') {
      throw new TypeError('call方法的调用标识符必须为函数!')
    }
    var ctx = ctx || window, args = [], ret
    ctx.fn = this
    for (var i = 1, len = arguments.length; i < len; i++) {
      args.push(arguments[i])
    }
    ret = new Function('ctx', 'args', 'return ctx.fn(...args)')(ctx, args)
    delete ctx.fn
    return ret
  }
}

Function#apply()

JavaScript
if (!Function.prototype.apply) {
  Function.prototype.apply = function (ctx, arr) {
    if (typeof this !== 'function') {
      throw new TypeError('apply方法的调用标识符必须为函数!')
    }
    var ctx = ctx || window, args = [], ret
    ctx.fn = this
    if (!arr) {
      ret = ctx.fn()
    } else {
      for (var i = 0, len = arr.length; i < len; i++) {
        args.push('arr[' + i + ']')
      }
      ret = eval('ctx.fn(' + args + ')')
    }
    delete ctx.fn
    return ret
  }
}

Function#bind()

JavaScript
if (!Function.prototype.bind) {
  Function.prototype.bind = function (ctx) {
    if (typeof this !== 'function') {
      throw new TypeError('bind方法的调用标识符必须为函数!')
    }
    var self = this,
      args = Array.prototype.slice.call(arguments, 1),
      fBind = function () {
        var _args = Array.prototype.slice.call(arguments)
        return self.apply(this instanceof fBind ? this : ctx, args.concat(_args))
      }
    fBind.prototype = Object.create(this.prototype)
    return fBind
  }
}