我知道 JavaScript 函数可以接受“任意”数量的参数。
function f(){};
f(1,2,3,4 /*...*/);
但我想知道“任何”的数量是否真的有限制?
例如,假设我将一百万个参数传递给f()
。那行得通吗?还是口译员会倒下?
我猜最大值是 (a) 特定于实现或 (b) (2^32)-1
,因为该arguments
对象类似于数组。
我在语言规范中没有看到这一点,但我可能没有连接一些点。
我知道 JavaScript 函数可以接受“任意”数量的参数。
function f(){};
f(1,2,3,4 /*...*/);
但我想知道“任何”的数量是否真的有限制?
例如,假设我将一百万个参数传递给f()
。那行得通吗?还是口译员会倒下?
我猜最大值是 (a) 特定于实现或 (b) (2^32)-1
,因为该arguments
对象类似于数组。
我在语言规范中没有看到这一点,但我可能没有连接一些点。
尽管没有具体限制规范中的理论最大参数数量(正如thefortheye的回答所 指出的那样)。当然也有实际限制。这些限制是完全依赖于实现的,最有可能,也将取决于究竟在如何你调用的函数。
我创建了这个小提琴作为实验。
function testArgs() {
console.log(arguments.length);
}
var argLen = 0;
for (var i = 1; i < 32; i++) {
argLen = (argLen << 1) + 1;
testArgs.apply(null, new Array(argLen));
}
这是我的结果:
Chrome 33.0.1750.154 m:最后一次成功的测试是65535 个参数。之后它失败了:
未捕获的 RangeError:超出最大调用堆栈大小
Firefox 27.0.1:最后一次成功的测试是262143 个参数。之后它失败了:
RangeError:传递给 Function.prototype.apply 的参数数组太大
Internet Explorer 11:最后一次成功的测试是131071 个参数。之后它失败了:
RangeError: SCRIPT28: 堆栈空间不足
Opera 12.17:最后一次成功的测试是1048576 个参数。之后它失败了:
错误:Function.prototype.apply:argArray 太大
当然,这里可能还有其他因素在起作用,您可能会得到不同的结果。
这里是一个替代的小提琴使用创建的eval
。同样,您可能会得到不同的结果。
Chrome 33.0.1750.154 m:最后一次成功的测试是32767 个参数。之后它失败了:
未捕获的语法错误:函数调用中的参数过多(仅允许 32766)
这个特别有趣,因为 Chrome 本身似乎对实际允许的参数数量感到困惑。
Firefox 27.0.1:最后一次成功的测试是32767 个参数。之后它失败了:
脚本太大
Internet Explorer 11:上次成功的测试是32767 个参数。之后它失败了:
RangeError: SCRIPT7: 内存不足
Opera 12.17:最后一次成功的测试是4194303 个参数。之后它失败了:
内存不足; 脚本终止。
List 类型用于解释新表达式、函数调用和其他需要简单值列表的算法中的参数列表(见 11.2.4)的评估......这些序列可以是任意长度。
所以标准没有限制。当然,如果您的代码在现实世界中运行,而不是在标准域中运行,那么显然存在一些限制(例如,宇宙中的粒子数)。
有两种方法可以将参数传递给函数。
f(a, b, c)
f.apply(null, [a, b, c])
对于大型参数列表,后一种方式是更现实的场景。
转到此JSFiddle以查看您当前浏览器的每个限制。
我自己尝试了几个浏览器:
| apply() | literal
----------------------------
Chrome 14 | 131155 | 32767
Chrome 35 | 126213 | 65535
Firefox 30 | 500001 | 65535
IE 9 | 254335 | 65533
IE 10 | 253667 | 65533
IE 11 | 252447 | 65533
Opera 22 | 126063 | 65535
Safari 4 | 524215 | 524205
Safari 7 | 65537 | 522159
我在不同的机器上看到了许多这些数字的差异,所以我相信除了浏览器(操作系统?)之外还有其他因素在起作用。
这是一个真正的问题,而不是一些琐事。一个真实世界的例子:
Google Closure 库定义了以下函数。
goog.crypt.byteArrayToString = function(array) {
return String.fromCharCode.apply(null, array);
};
仅当字符串的长度在浏览器可以通过Function.prototype.apply
.
该功能后来被修补,使该功能明显更加复杂。
仅供参考,2012 年 3 月提交的一个开放的Webkit 问题讨论了参数限制。
List 类型用于解释新表达式、函数调用和其他需要简单值列表的算法中的参数列表(见 11.2.4)的计算。List 类型的值是简单有序的值序列。这些序列可以是任何长度。
因此,该标准对参数数量没有任何限制,仅受内存限制。
> 来自计算机愚蠢
就我而言,极限是“足够大”!
这完全取决于客户端的强大程度。
因为浏览器会失去它的内存,如果你要传递数百万个参数。
每个变量都有一些内存。因此浏览器可以毫无问题地为每个变量分配一些内存,直到它本身没有内存可以运行。