JavaScript 函数可以接受的参数有最大数量吗?

IT技术 javascript
2021-01-21 02:26:22

我知道 JavaScript 函数可以接受“任意”数量的参数。

function f(){};
f(1,2,3,4 /*...*/);

但我想知道“任何”的数量是否真的有限制?

例如,假设我将一百万个参数传递给f()那行得通吗?还是口译员会倒下?

我猜最大值是 (a) 特定于实现或 (b) (2^32)-1,因为该arguments对象类似于数组。

我在语言规范中没有看到这一点,但我可能没有连接一些点。

6个回答

尽管没有具体限制规范中的理论最大参数数量(正如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 个参数。之后它失败了:

    内存不足; 脚本终止。

是的,这完全取决于 OP 的想法。我无法想象为一个函数输入 100,000 个参数,所以.apply()看起来更有可能。但后来他没有提到.apply(),所以也许他打算做一些evaling。
2021-03-12 02:26:22
您的示例正在测试.apply()超过问题中所示传递的函数参数的最大值它们不一定相同。这是一个演示,我使用Function构造函数从字符串创建了一个函数该函数调用您的testArgs()函数,向其传递 100,000 个参数。仅仅创建该函数失败SyntaxError: too many function arguments
2021-03-13 02:26:22
@cookiemonster 你是对的。有许多不同的因素可能会限制最大数量,不同的调用方法可能会产生不同的结果。我想我应该多强调一下第一句话。
2021-03-25 02:26:22
@GladstoneKeep 正确。我的测试是关于找出给定浏览器的大致实际限制。
2021-03-27 02:26:22
这很棒。尽管如果您使用apply和发送参数作为Array,则无论实际限制是什么(?),每个规范的理论最大值都是 4,294,967,295 个元素。
2021-03-29 02:26:22

ECMAScript 5.1,第 8.8 部分

List 类型用于解释新表达式、函数调用和其他需要简单值列表的算法中的参数列表(见 11.2.4)的评估......这些序列可以是任意长度。

所以标准没有限制。当然,如果您的代码在现实世界中运行,而不是在标准域中运行,那么显然存在一些限制(例如,宇宙中的粒子数)。

有两种方法可以将参数传递给函数。

  • “字面上地”: f(a, b, c)
  • 使用 apply(): 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 问题讨论了参数限制。

根据ECMA Script 5.1 标准规范List

List 类型用于解释新表达式、函数调用和其他需要简单值列表的算法中的参数列表(见 11.2.4)的计算。List 类型的值是简单有序的值序列。这些序列可以是任何长度。

因此,该标准对参数数量没有任何限制,仅受内存限制。

计算机愚蠢
> 来自计算机愚蠢

就我而言,极限是“足够大”!

“极限是‘够大’!” 除非不是。bugs.webkit.org/show_bug.cgi?id=80797
2021-03-29 02:26:22

这完全取决于客户端的强大程度。

因为浏览器会失去它的内存,如果你要传递数百万个参数。

每个变量都有一些内存。因此浏览器可以毫无问题地为每个变量分配一些内存,直到它本身没有内存可以运行。