JavaScript 함수에 가변 개수의 인수를 보낼 수 있습니까?


171

배열에서 JavaScript 함수에 가변 개수의 인수를 보낼 수 있습니까?

var arr = ['a','b','c']

var func = function()
{
    // debug 
    alert(arguments.length);
    //
    for(arg in arguments)
        alert(arg);
}

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'

나는 최근에 많은 파이썬을 작성했으며 varargs를 받아 보낼 수있는 훌륭한 패턴입니다. 예 :

def func(*args):
   print len(args)
   for i in args:
       print i

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(*arr) // prints 4 which is what I want, then 'a','b','c','d'

자바 스크립트를 처리 할 배열 보내는 것이 가능 으로 인수 배열을?


4
객체 for - in와 함께 루프 를 사용하는 것은 좋지 않습니다. 속성을 arguments반복하는 루프에 '정상'을 length대신 사용해야합니다.
— Yi Jiang

2
그것은 결코 문제가되지 않았습니다. 왜 그런지에 대해 설명 할 수 있습니까? arguments 객체는 agruments [0..length-1] 버전을 사용하는 경우 성능이 무시할 정도로 거의 작습니다.
— Fire Crow


1
인수는 실제 배열이 아니라 특수 객체라고 생각하므로 JS 구현에 따라 "in"구문이 작동하지 않을 수 있습니다.
— O'Rooney

답변:


209

업데이트 : ES6부터 함수를 호출 할 때 간단히 스프레드 구문을 사용할 수 있습니다 .

func(...arr);

ES6은 또한 인수를 배열로 취급하려는 경우 매개 변수 목록에서 다음과 같은 스프레드 구문을 사용할 수도 있습니다.

function func(...args) {
  args.forEach(arg => console.log(arg))
}

const values = ['a', 'b', 'c']
func(...values)
func(1, 2, 3)

예를 들어 처음 두 인수를 개별적으로 받거나 나머지를 배열로 받으려면 일반 매개 변수와 결합 할 수 있습니다.

function func(first, second, ...theRest) {
  //...
}

함수가 예상하는 인수의 수를 알 수 있다는 점에서 유용 할 수 있습니다.

var test = function (one, two, three) {}; 
test.length == 3;

그러나 어쨌든 임의의 수의 인수를 전달할 수 있습니다 ...

스프레드 구문은 짧고 "달콤하다"고 함수 호출에서 값 apply을 설정할 필요가없는 this경우이 방법이 사용됩니다.

다음은 적용 예입니다. 이전의 방법이었습니다.

var arr = ['a','b','c'];

function func() {
  console.log(this); // 'test'
  console.log(arguments.length); // 3

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

};

func.apply('test', arr);

요즘 난 단지 사용하는 것이 좋습니다 apply당신이 배열에서 임의의 인수 수를 통과해야하는 경우에만 및 설정된 this값입니다. apply는 IS 소요 this함수 호출에 사용되는 최초의 인수와 같은 값이 우리가 사용하는 경우, null비 엄격한 코드에서 this키워드는 글로벌 오브젝트 (창) 내부에 참조 할 funcStrict 모드에서, 명시 적으로 '사용하는 경우 엄격한 사용 '또는 ES 모듈에서 null사용됩니다.

또한 arguments객체는 실제로 배열이 아니라는 점에 유의하십시오 .

var argsArray = Array.prototype.slice.call(arguments);

그리고 ES6에서 :

const argsArray = [...arguments] // or Array.from(arguments)

그러나 arguments스프레드 구문 덕분에 오늘날 객체를 직접 사용하는 경우는 거의 없습니다 .


1
고마워, 적용은 트릭을 수행,이 경우 전화가 작동하지 않습니다. 실수로 쓰여졌습니까?
— Fire Crow

함수가 실제로 클래스의 멤버 인 경우 어떻게합니까? 이게 옳은 거니? theObject.member.apply (theObject, 인수);
— Baxissimo

4
Array.prototype.slice.call(arguments);V8과 같은 브라우저 JS 최적화를 방지합니다. 자세한 내용은 여기
— Dheeraj Bhaskar

2
1. 분명히, arguments찬성 중단 될 예정입니다 확산 연산자 . 나는 이것에 대한 출처가 없지만 어딘가에서 들었습니다. 2. MDN 상태 사용하여 해당 slice온 argumentsV8과 같은 엔진의 객체 방지 최적화. "despised Array 생성자" Array.from(arguments)또는을 사용하는 것이 좋습니다 [...arguments]. ES2015에 대한 답변을 업데이트 하시겠습니까?
— Braden Best

NB : 계속 해서 나만의 답을 썼습니다 .
— Braden Best

75

실제로 자바 스크립트 함수에 원하는만큼 많은 값을 전달할 수 있습니다. 명시 적으로 명명 된 매개 변수는 처음 몇 개의 값을 가져 오지만 모든 매개 변수는 인수 배열에 저장됩니다.

"unpacked"형식으로 arguments 배열을 전달하려면 apply를 사용할 수 있습니다 ( Functional Javascript ).

var otherFunc = function() {
   alert(arguments.length); // Outputs: 10
}

var myFunc = function() {
  alert(arguments.length); // Outputs: 10
  otherFunc.apply(this, arguments);
}
myFunc(1,2,3,4,5,6,7,8,9,10);

23

플랫 및 확산 운영자는 ES6, 자바 스크립트의 계획을 다음 버전의 일부입니다. 지금까지는 Firefox 만 지원합니다. 이 코드는 FF16 +에서 작동합니다.

var arr = ['quick', 'brown', 'lazy'];

var sprintf = function(str, ...args)
{
    for (arg of args) {
        str = str.replace(/%s/, arg);
    }
    return str;
}

sprintf.apply(null, ['The %s %s fox jumps over the %s dog.', ...arr]);
sprintf('The %s %s fox jumps over the %s dog.', 'slow', 'red', 'sleeping');

스프레드에 대한 어색한 구문에 유의하십시오. 의 일반적인 구문 sprintf('The %s %s fox jumps over the %s dog.', ...arr);입니다 아직 지원되지 않습니다 . ES6 호환성 표는 여기에서 찾을 수 있습니다 .

for...of또 다른 ES6 추가 인의 사용에 주목하십시오 . for...in배열에 사용 하는 것은 나쁜 생각 입니다.


확산을위한 일반 구문은 이제 파이어 폭스와 크롬에서 지원
— 사용자

8

이 apply함수는 두 가지 인수를 취합니다. 객체 this가 바인딩되고 인수가 배열로 표현됩니다.

some_func = function (a, b) { return b }
some_func.apply(obj, ["arguments", "are", "here"])
// "are"

8

ES2015에는 두 가지 방법이 있습니다.

arguments객체

이 객체는 함수에 내장되어 있으며 적절하게 함수의 인수를 나타냅니다. 기술적으로 배열이 아니기 때문에 일반적인 배열 작업은 작동하지 않습니다. 제안 된 방법은 Array.from확산 연산자를 사용하여 배열을 생성하는 것입니다.

를 사용하여 다른 답변에 대한 언급을 보았습니다 slice. 하지마 최적화를 방지합니다 (출처 : MDN ).

Array.from(arguments)
[...arguments]

그러나 arguments함수가 입력으로 받아들이는 것을 숨기므로 문제 가된다고 주장합니다 . arguments기능은 일반적으로 다음과 같이 기록됩니다

function mean(){
    let args = [...arguments];
    return args.reduce((a,b)=>a+b) / args.length;
}

때때로 함수 헤더는 C와 같은 방식으로 인수를 문서화하기 위해 다음과 같이 작성됩니다.

function mean(/* ... */){ ... }

그러나 그것은 드물다.

왜 문제가되는지 예를 들어 C를 사용하십시오. C는 K & R C로 알려진 고대의 ANSI 이전의 방언과 역 호환됩니다. K & R C는 함수 프로토 타입이 빈 인수 목록을 가질 수 있도록합니다.

int myFunction();
/* This function accepts unspecified parameters */

ANSI C는 varargs( ...)에 대한 기능을 제공하고 void빈 인수 목록을 지정합니다.

int myFunction(void);
/* This function accepts no parameters */

많은 사람들 이 함수가 인수가 0이 될 것으로 예상 할 때 unspecified인수 목록 ( int myfunction();)을 사용하여 실수로 함수를 선언합니다 . 함수 가 인수 를 허용 하기 때문에 이것은 기술적으로 버그 입니다. 그것들의 수

varargsC 의 적절한 기능은 다음과 같은 형식을 취합니다.

int myFunction(int nargs, ...);

그리고 JavaScript는 실제로 이와 비슷한 것을 가지고 있습니다.

스프레드 연산자 / 휴면 파라미터

이미 스프레드 연산자를 보여 드렸습니다.

...name

그것은 매우 다재다능하고 함수의 argument-list ( "rest parameters")에서 varargs를 잘 문서화 된 방식으로 지정하기 위해 사용될 수 있습니다 :

function mean(...args){
    return args.reduce((a,b)=>a+b) / args.length;
}

또는 람다 식으로 :

((...args)=>args.reduce((a,b)=>a+b) / args.length)(1,2,3,4,5); // 3

스프레드 연산자를 선호합니다. 깨끗하고 자체 문서화됩니다.


2
난 당신이 더 최근의 옵션에서 작성 기쁘다 있도록 업데이트 된 답변을 주셔서 감사합니다,이 게시물 선행은 2015 ES
— 화재 크로우

5

이것을 splat연산자 라고합니다 . JavaScript를 사용하여 apply다음을 수행 할 수 있습니다 .

var arr = ['a','b','c','d'];
var func = function() {
    // debug 
    console.log(arguments.length);
    console.log(arguments);
}
func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'
func.apply(null, arr); 

4

ES6에서는에 대한 나머지 매개 변수 를 사용할 수 있습니다 varagrs. 인수 목록을 받아서 배열로 변환합니다.

function logArgs(...args) {
    console.log(args.length)
    for(let arg of args) {
        console.log(arg)
    }
}

2

변수 인수 및 정수 배열의 정수 합계를 계산하는 샘플 프로그램입니다. 도움이 되었기를 바랍니다.

var CalculateSum = function(){
    calculateSumService.apply( null, arguments );
}

var calculateSumService = function(){
    var sum = 0;

    if( arguments.length === 1){
        var args = arguments[0];

        for(var i = 0;i<args.length; i++){
           sum += args[i]; 
        }
    }else{
        for(var i = 0;i<arguments.length; i++){
           sum += arguments[i]; 
        }        
    }

     alert(sum);

}


//Sample method call

// CalculateSum(10,20,30);         

// CalculateSum([10,20,30,40,50]);

// CalculateSum(10,20);

1
참고 사항 : 1. 변수를 var선언 function scope합니다. new let및 const키워드 (ES 2015)는 block scope변수를 선언 합니다. 그러나 ES 2015 이전에는 실제 상황에서 변수가 함수의 최상위에 유지되어야했습니다. 2. 배열을 인수로 잘못 받아 들여서 정수 값 1 개가 주어지면 함수가 중단됩니다 (질문은 varargs에 대해 묻습니다. 배열을 인수로 받아들이지 않음) CalculateSum(6) -> 0. (다음 포스트에서 계속)
— Braden Best

1
3. 같은 디버그 기능을 사용하지 마십시오 alert. 실제로는 alert/prompt/confirm마침표를 사용하지 마십시오 . console.log디버깅 할 때 대신 사용하십시오 . 4. 함수는 return값을 보내지 말고 값을 보내야 alert합니다. 5. PascalCase데이터의 "유형"을 나타내지 않는 한 피 하십시오. 즉 수업입니다. camelCase또는 under_score대신 사용하십시오 . 4. 함수를 선언하는 방식이 마음에 들지 않습니다. 특정 시점에서 변경var f = function(){ ... } 하기를 원한다는 것을 의미합니다 . 대신 기존 구문을 사용하십시오 . function name(){ ... }
— Braden Best

이러한 모든 비판 요점을 설명하기 위해 귀하의 답변에 향상된 기능 버전 이 있습니다.
— Braden Best

2
(function(window) {
  var proxied = window.alert;
  window.alert = function() {
    return proxied.apply(window, arguments);
  };
}(this));

alert(13, 37);

1

에서 이곳으로 보내진 사람들을 위해 다른 하나의 함수에서 인수 전달 변수 번호 (이해야 하지 이 질문의 중복으로 표시) :

한 함수에서 다른 함수로 가변 개수의 인수를 전달하려는 경우 JavaScript 1.8.5부터 apply()두 번째 함수 를 호출 하고 arguments매개 변수를 전달하면 됩니다.

var caller = function()
{
    callee.apply( null, arguments );
}

var callee = function()
{
    alert( arguments.length );
}

caller( "Hello", "World!", 88 ); // Shows "3".

참고 : 첫 번째 인수는 this사용할 매개 변수입니다. 전달 null은 전역 컨텍스트에서 함수를 호출합니다. 즉 일부 객체의 메소드 대신 전역 함수로 호출합니다.

이 문서 에 따르면 ECMAScript 5 사양 apply()은 엄격하게 Array 대신 "일반적인 배열과 유사한 객체"를 사용 하도록 메소드를 재정의했습니다 . 따라서 arguments목록을 두 번째 함수로 직접 전달할 수 있습니다 .

Chrome 28.0, Safari 6.0.5 및 IE 10에서 테스트되었습니다 . 이 JSFiddle로 사용해보십시오 .


0

예, 변수 번호를 전달할 수 있습니다. 함수에 대한 인수. apply이것을 달성하기 위해 사용할 수 있습니다 .

예 :

var arr = ["Hi","How","are","you"];

function applyTest(){
    var arg = arguments.length;
    console.log(arg);
}

applyTest.apply(null,arr);

0

함수가 배열 인수 또는 변수 인수에 반응하도록 하시겠습니까? 후자의 경우 다음을 시도하십시오.

var func = function(...rest) {
  alert(rest.length);

  // In JS, don't use for..in with arrays
  // use for..of that consumes array's pre-defined iterator
  // or a more functional approach
  rest.forEach((v) => console.log(v));
};

그러나 배열 인수를 처리하려면

var fn = function(arr) {
  alert(arr.length);

  for(var i of arr) {
    console.log(i);
  }
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.