MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

翻譯不完整。請協助 翻譯此英文文件

apply() 方法會呼叫一個以 this 的代表值和一個陣列形式的值組(或是一個 array-like object )為參數的函式。

注意: 這個函式的語法和和call() 幾乎一樣,最大的不同是 call() 接受一連串的參數,而 apply() 接受一組陣列形式的參數

語法

fun.apply(thisArg, [argsArray])

參數

thisArg
讓 fun 呼叫時可以視為 this  的值。注意,這可能並不是最後會在方法裡看見的值:如果這是一個在非 non-strict mode 下運作的程式碼,nullundefined 將會被全域物件取代,而原始類別將被封裝。
argsArray
一個 array-like object ,定義了 fun 要呼叫的一組參數,如果沒有需要提供,可以傳入 nullundefined 。從 ECMAScript 5 開始,這些參數不僅可以是泛型的 array-like object ,而不一定要是一組陣列。查看下方的browser compatibility 資訊。

回傳值

傳入 this 值及一組參數後得到的結果。

描述

在呼叫一個現存的函式時,你可以傳入不同的 this 物件值。this 參考到現在的物件,也就是正在執行的物件。apply 讓你可以只寫一次方法後,讓其他物件也繼承到這個方法,而不用一再重寫。

apply 與 call() 非常相似,不同的是支援的傳入參數類型。使用陣列形式的參數,而不是命名過的接收參數。使用 apply 時,你可以選擇使用陣列實字:fun.apply(this, ['eat', 'bananas']); 或是 Array 物件: fun.apply(this, new Array('eat', 'bananas'))。

除此之外,你也可以使用 arguments 代表 argsArray 參數。arguments 是在函式裡的區域變數,可用來存取所有沒有特別被所呼叫物件指定的傳入參數。因此,使用 apply 時你不需要知道所呼叫函式的指定參數。使用 arguments 把所有參數傳入呼叫的方法裡,而被呼叫的方法會接手處理這些參數。

從 ECMAScript 5th 版本後,也可以使用陣列形式的物件,在實踐上這代表他會擁有 length 以及整數範圍  (0...length-1) 的屬性。舉例來說,你可以使用 NodeList  或是一個像這樣的自定義屬性: { 'length': 2, '0': 'eat', '1': 'bananas' }。

一般瀏覽器,包括 Chrome 14 及 Internet Explorer 9,仍不支援陣列形式的物件,所以會對此丟出一個錯誤。

範例

Using apply to chain constructors

You can use apply to chain constructors for an object, similar to Java. In the following example we will create a global Function method called construct, which will enable you to use an array-like object with a constructor instead of an arguments list.

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

Note: The Object.create() method used above is relatively new. For an alternative method using closures, please consider the following alternative:

Function.prototype.construct = function(aArgs) {
  var fConstructor = this, fNewConstr = function() { 
    fConstructor.apply(this, aArgs); 
  };
  fNewConstr.prototype = fConstructor.prototype;
  return new fNewConstr();
};

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);                // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor);              // logs 'MyConstructor'

Note: This non-native Function.construct method will not work with some native constructors (like Date, for example). In these cases you have to use the Function.prototype.bind method (for example, imagine having an array like the following, to be used with Date constructor: [2012, 11, 4]; in this case you have to write something like: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))() — anyhow this is not the best way to do things and probably should not be used in any production environment).

Using apply and built-in functions

Clever usage of apply allows you to use built-ins functions for some tasks that otherwise probably would have been written by looping over the array values. As an example here we are going to use Math.max/Math.min to find out the maximum/minimum value in an array.

// 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);

// vs. simple loop based algorithm
max = -Infinity, min = +Infinity;

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max) {
    max = numbers[i];
  }
  if (numbers[i] < min) {
    min = numbers[i];
  }
}

But beware: in using apply this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. (To illustrate this latter case: if such an engine had a limit of four arguments [actual limits are of course significantly higher], it would be as if the arguments 5, 6, 2, 3 had been passed to apply in the examples above, rather than the full array.) If your value array might grow into the tens of thousands, use a hybrid strategy: apply your function to chunks of the array at a time:

function minOfArray(arr) {
  var min = Infinity;
  var QUANTUM = 32768;

  for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
    var submin = Math.min.apply(null, 
                                arr.slice(i, Math.min(i+QUANTUM, len)));
    min = Math.min(submin, min);
  }

  return min;
}

var min = minOfArray([5, 6, 2, 3, 7]);

Using apply in "monkey-patching"

Apply can be the best way to monkey-patch a built-in function of Firefox, or JS libraries. Given someobject.foo function, you can modify the function in a somewhat hacky way, like so:

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

This method is especially handy where you want to debug events, or interface with something that has no API like the various .on([event]... events, such as those usable on the Devtools Inspector).

Specifications

Specification Status Comment
ECMAScript 3rd Edition (ECMA-262) Standard Initial definition. Implemented in JavaScript 1.3.
ECMAScript 5.1 (ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Standard  
ECMAScript 2017 Draft (ECMA-262)
The definition of 'Function.prototype.apply' in that specification.
Draft  

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) (Yes) (Yes) (Yes) (Yes)
ES 5.1 generic array-like object as arguments (Yes) 4.0 (2.0) ? ? ?
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)
ES 5.1 generic array-like object as arguments ? ? 4.0 (2.0) ? ? ?

See also

文件標籤與貢獻者

 此頁面的貢獻者: Snailpool
 最近更新: Snailpool,