함수의 JavaScript 변수 개수


531

JavaScript에서 함수에 대해 "무제한"변수를 허용하는 방법이 있습니까?

예:

load(var1, var2, var3, var4, var5, etc...)
load(var1)



1
@ 루크 아니, 그렇지 않아. 이 질문은 배열의 인수와 함께 임의의 수의 인수로 함수를 호출하는 방법을 묻습니다. 이러한 통화를 처리하는 방법을 묻습니다.
Scruuffy

1
보다 쉽게 ​​검색 할 수 있도록 이러한 기능을 '가변 함수'라고합니다.
gschenk

답변:


814

물론, 그냥 arguments물건을 사용하십시오 .

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

1
Tnx. Webview에서 안드로이드 네이티브 코드에서 자바 스크립트로 문자열을 구문 분석하는 데 좋습니다.
Johan Hoeksma

4
이 솔루션은 저에게 가장 효과적이었습니다. 감사. arguments 키워드 HERE 에 대한 추가 정보 .
사용자 2

26
arguments특별한 "Array-like"객체입니다. 즉, 길이는 있지만 다른 배열 함수는 없습니다. 자세한 내용은 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 를 참조하십시오.이 답변은 stackoverflow.com/a/13145228/1766230
Luke

4
흥미롭게도 Javascript의 Array 메서드는 length속성 이있는 객체에서 작동하도록 정의되었습니다 . 여기에는 arguments개체가 포함됩니다 . 이것을 알면 메소드 concat가 호출 된 '배열' 의 복사본 을 반환 하므로 arguments객체를 다음과 같이 실제 배열 로 쉽게 변환 할 수 있습니다 var args = [].concat.call(arguments). 어떤 사람들은 Array.prototype.concat.call대신 에 사용하는 것을 선호 하지만, 나는 좋아요 [], 그들은 짧고 달콤합니다!
Stijn de Witt

2
@YasirJan 사용[...arguments].join()
Willian D. Andrade

179

(대부분의) 최신 브라우저에서는 다음 구문을 사용하여 가변 개수의 인수를 사용할 수 있습니다.

function my_log(...args) {
     // args is an Array
     console.log(args);
     // You can pass this array as parameters to another function
     console.log(...args);
}

다음은 작은 예입니다.

function foo(x, ...args) {
  console.log(x, args, ...args, arguments);
}

foo('a', 'b', 'c', z='d')

=>

a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
    0: "a"
    1: "b"
    2: "c"
    3: "d"
    length: 4

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters에 대한 설명서 및 추가 예제


27
참고로 "나머지 매개 변수 구문"이라고합니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
tanguy_k

4
+1 우아하고 깨끗한 솔루션입니다. 긴 매개 변수 목록을 다른 함수 호출로 전달하는 데 특히 적합하며 해당 변수 매개 변수가 임의의 위치에있을 수 있습니다.
haxpor

3
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 에 따르면 IE에서는 지원되지 않습니다.
Roee Gavirel

2
다음은 테이블을 보여주는 브라우저 지원입니다 - caniuse.com/#feat=rest-parameters
브라이언 번스

1
좋은 답변입니다!
Ashish

113

또 다른 옵션은 컨텍스트 객체에서 인수를 전달하는 것입니다.

function load(context)
{
    // do whatever with context.name, context.address, etc
}

이렇게 사용하세요

load({name:'Ken',address:'secret',unused:true})

이것은 원하는만큼 명명 된 인수를 추가 할 수 있다는 장점이 있으며, 함수는 적절하다고 판단되는대로 사용할 수 있습니다.


4
인수 순서에 대한 커플 링을 제거하므로 더 좋습니다. 느슨하게 연결된 인터페이스는 좋은 표준 관행입니다.
Jonas Schubert Erlandsson

9
물론 어떤 경우에는 더 좋습니다. 그러나 개별 인수가 실제로 서로 관련이 없거나 배열 요소와 같은 의미를 갖는 것으로 가정 해 봅시다. 그렇다면 OP의 방법이 가장 좋습니다.
rvighne

1
원하는 경우 context코드로 인수를 작성하고 사용하기 전에 전달할 수 있기 때문에 좋습니다 .
Nate CK

46

나는 가장 역동적 인 Ken의 대답에 동의하며 한 걸음 더 나아가고 싶습니다. 다른 인수로 여러 번 호출하는 함수 인 경우 Ken의 디자인을 사용하지만 기본값을 추가하십시오.

function load(context) {

    var defaults = {
        parameter1: defaultValue1,
        parameter2: defaultValue2,
        ...
    };

    var context = extend(defaults, context);

    // do stuff
}

이 방법으로 매개 변수가 많지만 함수를 호출 할 때마다 매개 변수를 설정할 필요가없는 경우 기본값이 아닌 값을 지정하기 만하면됩니다. extend 메소드의 경우 jQuery의 extend 메소드 ( $.extend())를 사용하거나 직접 작성하거나 다음을 사용할 수 있습니다.

function extend() {
    for (var i = 1; i < arguments.length; i++)
        for (var key in arguments[i])
            if (arguments[i].hasOwnProperty(key))
                arguments[0][key] = arguments[i][key];
    return arguments[0];
}

컨텍스트 객체를 기본값과 병합하고 객체의 정의되지 않은 값을 기본값으로 채 웁니다.


3
+1. 좋은 트릭. 모든 매개 변수를 정의, 기본값 또는 기타 방식으로 지정하기 위해 많은 보일러 플레이트를 저장합니다.
Neil

1
Underscore의 _.defaults() 방법은 지정된 인수와 기본 인수를 병합하는 매우 좋은 대안입니다.
mbeasley 2013

18

예, 이처럼 :

function load()
{
  var var0 = arguments[0];
  var var1 = arguments[1];
}

load(1,2);

18

Ramast가 지적했듯이 rest 매개 변수 구문을 사용하는 것이 좋습니다.

function (a, b, ...args) {}

방금 ... args 인수의 멋진 속성을 추가하고 싶습니다.

  1. 배열이며 인수와 같은 객체가 아닙니다. 이를 통해 맵 또는 정렬과 같은 기능을 직접 적용 할 수 있습니다.
  2. 모든 매개 변수를 포함하지는 않지만 전달 된 매개 변수 만 포함합니다. 예를 들어, args는 인수 3에 인수 3을 포함합니다.

15

이미 언급했듯이 arguments객체를 사용하여 가변 개수의 함수 매개 변수를 검색 할 수 있습니다 .

동일한 인수로 다른 함수를 호출하려면을 사용하십시오 apply. arguments배열 로 변환 하여 인수를 추가하거나 제거 할 수도 있습니다 . 예를 들어이 함수는 콘솔에 로깅하기 전에 텍스트를 삽입합니다.

log() {
    let args = Array.prototype.slice.call(arguments);
    args = ['MyObjectName', this.id_].concat(args);
    console.log.apply(console, args);
}

인수를 배열로 변환하는 좋은 솔루션입니다. 오늘 저에게 도움이되었습니다.
Dmytro Medvid

8

비록 이름있는 인수 접근법이 유용하고 유연하다는 데 동의하지만 (순서에 신경 쓰지 않는 한 인수가 가장 쉬운 경우는 아니지만) mbeasley 접근법의 비용 (기본값 및 확장 사용)에 대해 우려합니다. 이는 기본값을 가져 오는 데 드는 막대한 비용입니다. 먼저, 기본값은 함수 내에서 정의되므로 모든 호출에서 다시 채워집니다. 둘째, ||를 사용하여 명명 된 값을 쉽게 읽고 기본값을 동시에 설정할 수 있습니다. 이 정보를 얻기 위해 또 다른 새 객체를 만들어 병합 할 필요가 없습니다.

function load(context) {
   var parameter1 = context.parameter1 || defaultValue1,
       parameter2 = context.parameter2 || defaultValue2;

   // do stuff
}

이것은 대략 같은 양의 코드 (약간 더 많을 수도 있음)이지만 런타임 비용의 일부 여야합니다.


해는 값의 유형 또는 기본값 자체에 따라 다르지만 동의합니다. 그렇지 않으면, (parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)또는 적은 코드 량을 위해 다음과 같은 작은 도우미 기능이 있습니다 : function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)대체 패턴을 제공하십시오. 그러나 요점은 여전히 ​​설명합니다 . 모든 함수 호출에 대해 추가 객체 만들고 값 비싼 루프를 실행하여 몇 가지 기본값을 설정하는 것은 엄청난 양의 오버 헤드입니다.
mcurland

7

@roufamatic은 arguments 키워드를 사용하고 @Ken은 사용을위한 객체의 훌륭한 예를 보여 주었지만이 인스턴스에서 진행중인 일을 진정으로 다루지 않았으며 미래 독자를 혼란스럽게하거나 기능을 명시 적으로 명시하지 않는 나쁜 습관을 심을 수 있습니다 / method는 다양한 양의 인수 / 매개 변수를 사용합니다.

function varyArg () {
    return arguments[0] + arguments[1];
}

다른 개발자가 코드를 살펴보면이 함수가 매개 변수를 사용하지 않는다고 가정하는 것이 매우 쉽습니다. 특히 그 개발자가 arguments 키워드에 특권이 없다면 . 이 때문에 스타일 가이드 라인을 따르고 일관성을 유지하는 것이 좋습니다. 모든 예에서 Google을 사용합니다.

동일한 함수에 변수 매개 변수가 있다고 명시 적으로 설명하겠습니다.

function varyArg (var_args) {
    return arguments[0] + arguments[1];
}

객체 매개 변수 VS var_args

데이터 맵의 유일한 승인되고 고려되는 모범 사례 방법이므로 개체가 필요할 수 있습니다. 연관 배열은 눈살을 찌푸리고 낙담합니다.

SIDENOTE : arguments 키워드는 실제로 숫자를 키로 사용하여 객체를 반환합니다. 프로토 타입 상속도 객체 패밀리입니다. JS에서 올바른 배열 사용법은 응답 끝을 참조하십시오.

이 경우에도 명시 적으로 명시 할 수 있습니다. 참고 :이 명명 규칙은 Google에서 제공하지 않지만 param 유형의 명시 적 선언의 예입니다. 코드에서보다 엄격한 형식의 패턴을 만들려는 경우 중요합니다.

function varyArg (args_obj) {
    return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});

어느 것을 선택해야합니까?

이것은 기능과 프로그램의 요구에 따라 다릅니다. 예를 들어 전달 된 모든 인수에서 반복 프로세스를 기반으로 값 기반을 반환하려는 경우 인수 키워드를 사용하는 것이 가장 확실 합니다. 인수에 대한 정의와 데이터의 매핑이 필요한 경우 객체 방법을 사용하는 것이 좋습니다. 두 가지 예를 살펴보면 끝났습니다!

인수 사용법

function sumOfAll (var_args) {
    return arguments.reduce(function(a, b) {
        return a + b;
    }, 0);
}
sumOfAll(1,2,3); // returns 6

객체 사용법

function myObjArgs(args_obj) {
    // MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
    if (typeof args_obj !== "object") {
        return "Arguments passed must be in object form!";
    }

    return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old

객체 대신 배열에 액세스 ( "... args"rest 매개 변수)

답변 위에서 언급했듯이 arguments 키워드는 실제로 객체를 반환합니다. 이 때문에 배열에 사용하려는 메소드를 호출해야합니다. 이것의 예 :

Array.prototype.map.call(arguments, function (val, idx, arr) {});

이를 피하려면 rest 매개 변수를 사용하십시오.

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5

5

arguments함수 내 에서 객체를 사용하여 전달 된 모든 인수에 액세스 할 수 있습니다.


3

Ken이 제안한 것처럼 이름이 지정된 속성을 가진 객체를 전달하면 모든 호출에 임시 객체를 할당하고 해제하는 비용이 추가됩니다. 값이나 참조로 일반 인수를 전달하는 것이 일반적으로 가장 효율적입니다. 많은 응용 프로그램의 경우 성능이 중요하지 않지만 일부 응용 프로그램의 경우 성능이 중요 할 수 있습니다.

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