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 상태 사용하여 해당 sliceargumentsV8과 같은 엔진의 객체 방지 최적화. "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 letconst키워드 (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.