Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
Function 实例的 apply() 方法会以给定的 this 值和作为数组(或类数组对象)提供的 arguments 调用该函数。
调用 func 时提供的 this 值。如果函数不处于严格模式,则 null 和 undefined 会被替换为全局对象,原始值会被转换为对象。
argsArray 可选一个类数组对象,用于指定调用 func 时的参数,或者如果不需要向函数提供参数,则为 null 或 undefined。
使用指定的 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,例如:
一般而言,fn.apply(null, args) 等同于使用参数展开语法的 fn(...args),只是在前者的情况下,args 期望是类数组对象,而在后者的情况下,args 期望是可迭代对象。
警告:不要使用 apply() 进行构造函数链式调用(例如,实现继承)。这会将构造函数作为普通函数调用,这意味着 new.target 是 undefined,从而类会抛出错误,因为它们不能在没有 new 的情况下调用。请改用 Reflect.construct() 或 extends。
你可以使用 Array.prototype.push() 方法将元素追加到数组中。因为 push() 接受可变数量的参数,所以你也可以一次性添加多个元素。但是,如果你将一个数组传递给 push(),它实际上会将该数组作为单个元素添加,而不是逐个添加元素,导致最终得到一个数组内嵌的数组。另一方面,Array.prototype.concat() 在这种情况下具有期望的行为,但它不会将元素追加到已有数组中,而是创建并返回一个新数组。
在这种情况下,你可以使用 apply 隐式地将一个数组作为一系列参数展开。
使用展开语法可以达到相同的效果。
巧妙地使用 apply() 可以让你在某些情况下使用内置函数来完成一些任务,而这些任务通常需要手动遍历集合(或使用展开语法)。
例如,我们可以使用 Math.max() 和 Math.min() 来找出数组中的最大值和最小值。
但要注意:通过使用 apply()(或展开语法)来处理任意长的参数列表,你可能会超过 JavaScript 引擎的参数长度限制。
调用具有太多参数的函数(即超过数万个参数)的后果是未指定的,并且在不同的引擎中会有所不同。(JavaScriptCore 引擎将参数限制硬编码为 65536。)大多数引擎会抛出异常;但并没有规范要求阻止其他行为,例如任意限制应用函数实际接收的参数数量。为了说明后一种情况:假设这样的引擎限制为四个参数(实际限制当然要高得多),那么在上面的示例中,传递给 apply 的参数将变为 5, 6, 2, 3,而不是完整的数组。
如果你的值数组可能会增长到数万个,可以使用混合策略:将数组的片段分批通过 apply 调用函数:
| ECMAScript® 2027 Language Specification # sec-function.prototype.apply |
启用 JavaScript 以查看此浏览器兼容性表。