[javascript] JavaScript 함수가 허용 할 수있는 최대 인수 수가 있습니까?

JavaScript 함수는 “임의의”인수를 받아 들일 수 있다는 것을 알고 있습니다.

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

하지만 실제로 얼마나 많은 “무엇”이 될 수 있는지에 대한 제한이 있는지 궁금합니다.

예를 들어, f(). 작동할까요? 아니면 통역사가 넘어 질까요?

객체가 배열과 유사하기 (2^32)-1때문에 최대 값이 (a) 구현 별 또는 (b) 중 하나라고 추측하고 arguments있습니다.

나는 이것이 언어 사양에 언급되어 있지 않지만 일부 점을 연결하지 않을 수 있습니다.



답변

사양의 이론적 최대 인수 수를 제한하는 특정 사항은 없지만 ( theye 의 답변이 지적했듯이). 물론 실제적인 한계가 있습니다. 이러한 제한은 전적으로 구현에 따라 다르며 대부분 함수를 호출하는 방법에 따라 달라집니다 .


이 바이올린 을 실험으로 만들었습니다 .

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 개의 인수입니다. 그 후 실패했습니다.

    메모리 부족; 스크립트가 종료되었습니다.


답변

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

나는 다른 컴퓨터에서 이러한 숫자의 많은 차이를 보았 기 때문에 브라우저 (OS?) 외에 다른 요인이 있다고 생각합니다.


이것은 퀴즈 가 아니라 실제 문제 입니다. 실제 예 :

Google Closure Library는 다음 기능을 정의했습니다.

goog.crypt.byteArrayToString = function(array) {
  return String.fromCharCode.apply(null, array);
};

이것은 문자열의 길이가와 함께 전달할 수있는 인수 수에 대한 브라우저 제한 내에있는 경우에만 작동했습니다 Function.prototype.apply.

이 함수는 나중에 패치 되어 함수가 훨씬 더 복잡해졌습니다.


참고로 2012 년 3 월에 인수 제한을 논의 하는 공개 된 Webkit 문제가 있습니다.


답변

에 대한 ECMA 스크립트 5.1 표준 사양에List 따르면 ,

List 유형은 새 표현식, 함수 호출 및 간단한 값 목록이 필요한 기타 알고리즘에서 인수 목록 (11.2.4 참조)의 평가를 설명하는 데 사용됩니다. 목록 유형의 값은 단순히 순서가 지정된 값 시퀀스입니다. 이러한 시퀀스는 임의의 길이 일 수 있습니다.

따라서 표준은 인수 수에 제한이 없으며 메모리에 의해서만 제한됩니다.


답변

컴퓨터 어리 석음
> Computer Stupidities에서

내가 아는 한 한계는 “충분히 크다”!


답변

순전히 클라이언트가 얼마나 강력한 지에 달려 있습니다.

수백만 개의 인수를 전달하면 브라우저는 메모리를 잃게됩니다.

각 변수는 약간의 메모리를 보유합니다. 따라서 브라우저는 실행할 메모리가 없을 때까지 각 변수에 메모리를 할당하는 데 문제가 없습니다.


답변

맵 (객체 만)을 단일 매개 변수로 사용하십시오. 여전히 매개 변수 이름을 사용하고 원하는만큼 인수를 가질 수 있습니다. 그것은 당신이 전달할 수있는 이론적 인 무한한 수의 인수를 보장하지만, 당신은 여전히 ​​힙 공간에 의해 제한되어 있습니다.

let infiniteParameters = (w) => console.table(w);

infiniteParameters({
  name1 : "value1",
  name2 : "value2",
  // ...
});


답변

확인 방법은 다음과 같습니다.

let args = [];

while(true){
    try{
        (() => {})(...args);
        args.push(0);
    }catch(e){
        console.log(e.message);
        console.log(`Number of arguments: ${args.length}`);
        break;
    }
}