试一试
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 |
浏览器兼容性
加载中…