試一試
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
console.log(max);
// Expected output: 7
const min = Math.min.apply(null, numbers);
console.log(min);
// Expected output: 2
語法
apply(thisArg)
apply(thisArg, argsArray)
引數
返回值
指定 this 值和引數呼叫函式的結果。
描述
注意: 這個函式幾乎與 call() 相同,只是 call() 將函式引數作為單獨的列表傳入,而 apply() 則將它們組合在一個物件中(通常是陣列)——例如,func.call(this, "eat", "bananas") 對比 func.apply(this, ["eat", "bananas"])。
通常,在呼叫函式時,函式內部的 this 值是函式被訪問的物件。透過 apply(),您可以在呼叫現有函式時將任意值分配給 this,而無需先將函式作為屬性附加到物件上。這允許您將一個物件的方法用作通用實用函式。
您還可以使用任何類陣列物件作為第二個引數。實際上,這意味著它需要有一個 length 屬性,以及一個整數(“索引”)屬性,其範圍為 (0..length - 1)。例如,您可以使用 NodeList,或者一個自定義物件,如 { 'length': 2, '0': 'eat', '1': 'bananas' }。您也可以使用 arguments,例如
function wrapper() {
return anotherFn.apply(null, arguments);
}
function wrapper(...args) {
return anotherFn(...args);
}
一般來說,fn.apply(null, args) 等同於帶有引數展開語法的 fn(...args),只是 apply() 期望 args 是一個類陣列物件,而展開語法期望的是一個 可迭代 物件。
警告: 請勿使用 apply() 來連結建構函式(例如,來實現繼承)。這會將建構函式作為普通函式呼叫,這意味著 new.target 為 undefined,並且類會因為無法在沒有 new 的情況下呼叫而丟擲錯誤。請改用 Reflect.construct() 或 extends。
示例
使用 apply() 將一個數組追加到另一個數組
您可以使用 Array.prototype.push() 將一個元素追加到陣列中。因為 push() 接受可變數量的引數,所以您也可以一次性追加多個元素。但是,如果您將一個數組傳遞給 push(),它實際上會將該陣列作為一個單獨的元素新增,而不是單獨新增元素,最終結果是陣列中包含一個數組。另一方面,Array.prototype.concat() 在這種情況下可以實現所需行為,但它不會追加到現有陣列——它會建立並返回一個新陣列。
在這種情況下,您可以使用 apply 來隱式地將一個數組“展開”為一系列引數。
const array = ["a", "b"];
const elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
使用展開語法可以達到相同的效果。
const array = ["a", "b"];
const elements = [0, 1, 2];
array.push(...elements);
console.info(array); // ["a", "b", 0, 1, 2]
使用 apply() 和內建函式
巧妙使用 apply() 可以讓您使用內建函式來完成一些原本可能需要手動迴圈遍歷集合(或使用展開語法)的任務。
例如,我們可以使用 Math.max() 和 Math.min() 來找出陣列中的最大值和最小值。
// min/max number in an array
const numbers = [5, 6, 2, 3, 7];
// using Math.min/Math.max apply
let max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], …)
// or Math.max(5, 6, …)
let min = Math.min.apply(null, numbers);
// vs. loop based algorithm
max = -Infinity;
min = Infinity;
for (const n of numbers) {
if (n > max) {
max = n;
}
if (n < min) {
min = n;
}
}
但請注意:使用 apply()(或展開語法)並傳入任意長度的引數列表,您可能會面臨超出 JavaScript 引擎引數長度限制的風險。
用過多的引數(即,超過數萬個引數)呼叫函式的後果是未定義的,並且因引擎而異。(JavaScriptCore 引擎有一個硬編碼的 引數限制,為 65536)。大多數引擎會丟擲異常;但沒有規範性說明可以阻止其他行為,例如任意限制實際傳遞給被應用函式的引數數量。為了說明後一種情況:如果某個引擎的限制是四個引數(實際限制當然遠高於此),那麼在上面的示例中,就好像只將引數 5, 6, 2, 3 傳遞給了 apply,而不是整個陣列。
如果您的值陣列可能會增長到數萬個,請使用混合策略:一次將函式應用於陣列的各個塊
function minOfArray(arr) {
let min = Infinity;
const QUANTUM = 32768;
for (let i = 0; i < arr.length; i += QUANTUM) {
const subMin = Math.min.apply(
null,
arr.slice(i, Math.min(i + QUANTUM, arr.length)),
);
min = Math.min(subMin, min);
}
return min;
}
const min = minOfArray([5, 6, 2, 3, 7]);
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-function.prototype.apply |
瀏覽器相容性
載入中…