此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
Function.prototype.apply()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年7月.
Function 实例的apply() 方法会以给定的this 值和作为数组(或类数组对象)提供的arguments 调用该函数。
In this article
尝试一下
const numbers = [5, 6, 2, 3, 7];const max = Math.max.apply(null, numbers);console.log(max);// Expected output: 7const 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),只是在前者的情况下,args 期望是类数组对象,而在后者的情况下,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() 来找出数组中的最大值和最小值。
// 数组中的最小/最大值const numbers = [5, 6, 2, 3, 7];// 用 apply 调用 Math.min/Math.maxlet max = Math.max.apply(null, numbers);// 这等价于 Math.max(numbers[0], …) 或 Math.max(5, 6, …)let min = Math.min.apply(null, numbers);// 与基于简单循环的算法相比max = -Infinity;min = +Infinity;for (let i = 0; i < numbers.length; i++) { if (numbers[i] > max) { max = numbers[i]; } if (numbers[i] < min) { min = numbers[i]; }}但要注意:通过使用apply()(或展开语法)来处理任意长的参数列表,你可能会超过 JavaScript 引擎的参数长度限制。
调用具有太多参数的函数(即超过数万个参数)的后果是未指定的,并且在不同的引擎中会有所不同。(JavaScriptCore 引擎将参数限制硬编码为 65536。)大多数引擎会抛出异常;但并没有规范要求阻止其他行为,例如任意限制应用函数实际接收的参数数量。为了说明后一种情况:假设这样的引擎限制为四个参数(实际限制当然要高得多),那么在上面的示例中,传递给apply 的参数将变为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]);规范
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-function.prototype.apply> |