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


80

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

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

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

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

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

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


3
또한 이와 같은 큰 데이터 시퀀스는 별도의 인수가 아닌 배열 인 단일 인수로 전달되어야하므로 함수를 호출하기 위해 큰 데이터 세트로 전체 복사본을 만들 필요가 없습니다. 이것은 좋은 개발 관행에서 접할 수있는 것이 아니라 학문적 연습이어야합니다.
jfriend00 2014

1
@ jfriend00, 잊지 마세요 Function.prototype.apply. stackoverflow.com/questions/1379553/…
Paul Draper

@PaulDraper-에 대해 알고 .apply()있지만 입력 배열의 복사본도 만들고 있습니다. 요점은 매우 많은 수의 인수를 허용 할 것으로 예상되는 인터페이스를 일반 인수로 전달하도록 선언해서는 안된다는 것입니다. 배열을 전달하는 것이 훨씬 더 효율적이므로 데이터 사본을 만들 필요가 없습니다.
jfriend00

5
@ IngoBürk 이것은 이론적 인 질문이 아닙니다! 그러한 함수를 명시 적으로 작성하지 않더라도 ES 2015 스프레드 연산자와 Math.maxor Array.prototype.concat(...arrayOfArrays)(배열 배열을 평탄화하기 위해) 와 같은 함수를 사용하면 괴물 함수를 작성하지 않고도 동적으로 제한에 도달 할 수 있습니다. jfriend00에서 언급 한 오버 헤드가 항상 중요하지는 않습니다. 코드의 명확성은 몇 바이트의 메모리 나 CPU주기보다 더 중요하며, 스프레드 구문이 때때로 최선의 선택 일 수 있습니다. 내 단축 코드에 대한 "배열 평탄화"의 대안을 찾아보십시오 ...
Mörre

@ Mörre 내 코멘트 월 2014 년에서 6 월 2015 년까지 출시 된 ES5015 않네
잉고 버크

답변:


92

사양의 이론적 최대 인수 수를 제한하는 특정 사항은 없지만 ( 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 개의 인수입니다. 그 후 실패했습니다.

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


이것은 훌륭합니다. apply인수를으로 사용 하고 전송하는 Array경우 사양 당 이론적 최대 값은 실제 제한 (?)에 관계없이 4,294,967,295 개 요소입니다.
GladstoneKeep 2014 년

1
귀하의 예는 .apply()질문에 표시된 것처럼 전달 된 함수 인수보다 많은 최대 값을 테스트하고 있습니다. 반드시 동일하지는 않습니다. 다음Function생성자를 사용하여 문자열에서 함수를 만든 데모 입니다. 함수는 함수를 호출하여 testArgs()100,000 개의 인수를 전달합니다. 단순히 그 함수를 만드는 것은 실패합니다SyntaxError: too many function arguments
cookie monster

@cookiemonster 맞습니다. 최대 수를 제한 할 수있는 여러 요인이 있으며이를 호출하는 다른 방법은 다른 결과를 생성 할 수 있습니다. 첫 번째 문장을 좀 더 강조해야한다고 생각합니다.
pswg 2014 년

예, 그것은 모두 OP가 염두에 둔 것에 달려 있습니다. 함수에 100,000 개의 인수를 입력하는 것을 상상할 수 없으므로 .apply()더 가능성이 높아 보입니다. 그러나 그는 언급하지 않았 .apply()으므로 아마도 그는 일부 eval노래를 할 계획입니다 .
쿠키 몬스터

@GladstoneKeep 올바른. 내 테스트는 주어진 브라우저에서 대략 적인 실제 한계를 찾는 것 입니다.
pswg 2014 년

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

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


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

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

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

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

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


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


6

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

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

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



1

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

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

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


1

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

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

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

0

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

let args = [];

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.