Published on

Javascript中apply()的用法

Authors
  • avatar
    Name
    Pursue
    Twitter

Summary

Function.prototype.apply()将会调用一个以 this 和数组形式的 arguments 为参数的方法,而 call()方法则只是在第二个参数形式与之不同而已。

fun.apply(thisArg, [argsArray])
fun.call(thisArg, arg1, arg2, arg3...)

Description

每当要为一个新的对象添加一个方法时,有时不得不为其重写一个方法。而如果利用 apply 的话,只需要写一次方法,然后在这个新的对象中继承它即可,十分方便。

apply 和 call 方法十分相似,仅仅只是参数不同而已,但证实因为这一点,我们在用 apply 时不必知道被调用的对象的具体参数,可以只传递 arguments,如此一来,被调用的这个对象将负责 handle 传递的 agrumets.

Examples

1.Using apply to chain constructors

我们可以像 Java 那样,利用 apply 为一个对象创建构造链。在下面的例子中,我们将创建一个名为 construct 的全局方法,这个方法可以不必让你传递一个一个的参数,取而代之的则是传递一个参数数组。

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype)
  this.apply(oNew, aArgs)
  return oNew
}

Example usage:

function MyConstructor() {
  for (var nProp = 0; nProp < arguments.length; nProp++) {
    this['property' + nProp] = arguments[nProp]
  }
}

var myArray = [4, 'Hello world!', false]
var myInstance = MyConstructor.construct(myArray)

console.log(myInstance.property1) // 'Hello world!'
console.log(myInstance instanceof MyConstructor) // 'true'
console.log(myInstance.constructor) // 'MyConstructor'

2.Using apply and built-in functions

利用 apply 调用 javascript 的内建方法是一种比较聪明的用法,例如下面的例子,利用 apply 调用系统 max 方法获取最大值。一般如果你要在一个数组中找到最大或最小值,那将不得不进行 loop,即使利用系统自带的 max 函数,那也得传递有限个参数,十分不便。

/* min/max number in an array */
var numbers = [5, 6, 2, 3, 7]

/* using Math.min/Math.max apply */
var max = Math.max.apply(null, numbers) /* This about equal to Math.max(numbers[0], ...)
                                            or Math.max(5, 6, ...) */
var min = Math.min.apply(null, numbers)

3.Using apply in monkey-patching

apply 还是一种很好的扩展内置对象方法的方式。如下面的例子,已有 someobject.foo 方法, 你可以像黑客那样在其原有的基础上修改它,从而破坏其封装性。

var someobject = new Object()
someobject.foo = function () {
  console.log('This is the originalfoo function.')
}

var originalfoo = someobject.foo
someobject.foo = function () {
  // Do stuff before calling function
  console.log(arguments)
  // Call the function as it would have been called normally:
  originalfoo.apply(this, arguments)
  // Run stuff after, here.
}