Function.prototype.apply()
试试看
语法
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
在前者使用 apply()
时应为类似数组的对象,而在后者使用展开语法时应为 可迭代 对象。
警告: 不要使用 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. simple loop based algorithm
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
,而不是整个数组。
如果您的值数组可能会增长到数万个,请使用混合策略:一次将您的函数应用于数组的一部分
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 语言规范 # sec-function.prototype.apply |
浏览器兼容性
BCD 表格仅在浏览器中加载