JavaScript에서 "arguments"객체를 배열로 변환하려면 어떻게해야합니까?


433

argumentsJavaScript 의 객체는 이상한 사마귀입니다. 대부분의 상황에서 배열처럼 작동하지만 실제로 는 배열 객체 가 아닙니다 . 그 이후 완전히 다른 정말 뭔가 , 그것에서 유용한 기능이없는 Array.prototypeforEach, sort, filter,와 map.

간단한 for 루프를 사용하여 arguments 객체에서 새 배열을 구성하는 것은 간단합니다. 예를 들어이 함수는 인수를 정렬합니다.

function sortArgs() {
    var args = [];
    for (var i = 0; i < arguments.length; i++)
        args[i] = arguments[i];
    return args.sort();
}

그러나 이것은 매우 유용한 JavaScript 배열 함수에 액세스하기 위해 수행해야하는 다소 불쌍한 일입니다. 표준 라이브러리를 사용하여 기본 제공 방법이 있습니까?


답변:


725

나머지 매개 변수를 사용하는 ES6

ES6를 사용할 수있는 경우 다음을 사용할 수 있습니다.

나머지 매개 변수

function sortArgs(...args) {
  return args.sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();

링크 에서 읽을 수 있듯이

rest 매개 변수 구문을 사용하면 무한한 수의 인수를 배열로 나타낼 수 있습니다.

...구문 이 궁금하면 Spread Operator 라고하며 여기에서 더 읽을 수 있습니다 .

Array.from ()을 사용하는 ES6

Array.from 사용 :

function sortArgs() {
  return Array.from(arguments).sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();

Array.from Array-like 또는 Iterable 객체를 Array 인스턴스로 변환하기 만하면됩니다.



ES5

실제로 arguments 객체에 Arrayslice함수를 사용 하면 표준 JavaScript 배열로 변환됩니다. Array의 프로토 타입을 통해 수동으로 참조하면됩니다.

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}

왜 이것이 작동합니까? ECMAScript 5 문서 자체 에서 발췌 한 내용은 다음과 같습니다.

참고 :이 slice기능은 의도적으로 일반적입니다. 값이 Array 객체 일 필요는 없습니다 . 따라서 방법으로 사용하기 위해 다른 종류의 객체로 전송할 수 있습니다. slice함수가 호스트 객체에 성공적으로 적용될 수 있는지 여부 는 구현에 따라 다릅니다.

따라서 속성 slice이있는 모든 항목에서 편리하게 작동합니다.lengtharguments


경우 Array.prototype.slice너무 많은 당신을 위해 입의, 당신은 약간 배열 리터럴을 사용하여 축약 할 수 있습니다 :

var args = [].slice.call(arguments);

그러나 나는 이전 버전이 더 명시 적이라고 생각하는 경향이 있으므로 대신 선호합니다. 배열 리터럴 표기법을 남용하면 해키 느낌이 들고 이상하게 보입니다.


5
최근 Firefox 버전 (2.0?) 및 ECMAScript 5에는 이것을보다 간단하게 만드는 Array.slice 메소드가 있습니다. 다음과 같이 호출합니다 : var arge = Array.slice (arguments, 0) ;.
Matthew Crumley

9
무엇입니까 0? 전달하려는 인수가 없으므로 왜 사용할 수 var args = Array.prototype.slice.call(arguments);없습니까? [ MDC 인수 페이지 ] ( developer.mozilla.org/en/JavaScript/Reference/… )는 0.
Peter Ajtai

3
@ Barney-원래 질문이 인수를 정렬하려고하기 때문에 정렬이 필요합니다. 배열로 변환하려면 필요하지 않습니다.
Krease

17
"자바 스크립트 엔진 (예 : V8)에서 최적화를 방해하므로 인수를 자르면 안됩니다." -MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…에서
frameworkninja

3
나는 그것이 원래의 질문에 대답하고 있는지 확실하지 않습니다. 시간이 지났다. Firefox와 Chrome에서 ES6을 실험하면서 나머지 매개 변수function sortArgs(...argsToSort) { return argsToSort.sort(); }MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Kir Kanos

40

또한 참조 가치가 이 블루 버드 약속 라이브러리 위키 페이지를 하는 방법을 관리하는 방법을 보여줍니다 arguments함수 최적화 할 수있는 방법으로 배열로 객체를 V8 자바 스크립트 엔진 아래를 :

function doesntLeakArguments() {
    var args = new Array(arguments.length);
    for(var i = 0; i < args.length; ++i) {
        args[i] = arguments[i];
    }
    return args;
}

이 방법은에 유리하게 사용됩니다 var args = [].slice.call(arguments);. 저자는 또한 빌드 단계가 자세한 정보를 줄이는 방법을 보여줍니다.


2
+1하고 Bluebird Optimization Killer 페이지에 대한 링크에 감사드립니다. 추신 : 최근에 노드 최적화 프로젝트 에서이 최적화가 사용되는 것을 보았습니다 .
Yves M.

29
function sortArgs(){ return [].slice.call(arguments).sort() }

// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }

일부 배열 메소드는 의도적으로 대상 객체가 실제 배열 일 필요가 없도록 만들어졌습니다. 대상에는 length 및 index 라는 이름의 속성 만 있으면됩니다 (0 이상의 정수 여야 함).

[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})

12

사용하다:

function sortArguments() {
  return arguments.length === 1 ? [arguments[0]] :
                 Array.apply(null, arguments).sort();
}

Array(arg1, arg2, ...) 보고 [arg1, arg2, ...]

Array(str1) 보고 [str1]

Array(num1)num1요소 가있는 배열을 반환

인수 수를 확인해야합니다!

Array.slice 버전 (느리게) :

function sortArguments() {
  return Array.prototype.slice.call(arguments).sort();
}

Array.push 버전 (슬라이스보다 느리고 빠름) :

function sortArguments() {
  var args = [];
  Array.prototype.push.apply(args, arguments);
  return args.sort();
}

버전 이동 (느리지 만 작은 크기가 더 빠름) :

function sortArguments() {
  var args = [];
  for (var i = 0; i < arguments.length; ++i)
    args[i] = arguments[i];
  return args.sort();
}

Array.concat 버전 (가장 느림) :

function sortArguments() {
  return Array.prototype.concat.apply([], arguments).sort();
}

1
Array.concat의 병합 동작으로 인해 배열 인수가 허용됩니다. sortArguments (2, [3,0], 1)은 0,1,2,3을 반환합니다.
Hafthor

9

jQuery를 사용하는 경우 다음과 같은 의견을 쉽게 기억할 수 있습니다.

function sortArgs(){
  return $.makeArray(arguments).sort();
}

1
그것은 본질적으로 순수한 JS에서 찾고 있었지만 jQuery가 JS를 조금 더 쉽게 만드는 방법에 대한 확실한 예는 +1입니다.
Andrew Coleson

2
"프레임 워크 / 라이브러리에 다른 태그가 포함되어 있지 않으면 순수한 JavaScript 응답이 예상됩니다."
Michał Perłakowski

6

ECMAScript 6에서는과 같은 못생긴 해킹을 사용할 필요가 없습니다 Array.prototype.slice(). 대신 스프레드 구문 ( ...)을 사용할 수 있습니다 .

(function() {
  console.log([...arguments]);
}(1, 2, 3))

이상하게 보일지 모르지만 상당히 간단합니다. 단지 arguments'요소를 추출 하여 배열에 다시 넣습니다. 여전히 이해하지 못하는 경우 다음 예를 참조하십시오.

console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);

IE 11과 같은 일부 구형 브라우저에서는 작동하지 않으므로 이러한 브라우저를 지원하려면 Babel 을 사용해야합니다 .


5

다음은 인수를 배열로 변환하는 몇 가지 방법의 벤치 마크 입니다.

저에 관해서는, 소량의 논쟁에 대한 가장 좋은 해결책은 다음과 같습니다.

function sortArgs (){
  var q = [];
  for (var k = 0, l = arguments.length; k < l; k++){
    q[k] = arguments[k];
  }
  return q.sort();
}

다른 경우 :

function sortArgs (){ return Array.apply(null, arguments).sort(); }

벤치 마크의 경우 +1 현재 그래프에 따르면 sortArgsFirefox에서는 6 배 더 빠르지 만 최신 Chrome에서는 2 배 더 빠릅니다 Array.apply.
joeytwiddle

1
JS. V8 엔진 최적화를 막기 때문에 Array.prototype.slice가 더 이상 사용되지 않기 때문에 ES6가 널리 사용 가능할 때까지이 솔루션을 가장 잘 생각합니다. +1
Sasha

1
또한 Array.slice ()와 같은 Array 제네릭 메서드도 더 이상 사용되지 않습니다
Sasha

4

ECMAScript 6 spread operator를 사용하여 후행 매개 변수를 배열에 바인딩하는 것이 좋습니다 . 이 솔루션을 사용하면 arguments객체 를 만질 필요가 없으며 코드가 단순화됩니다. 이 솔루션의 단점은 대부분의 브라우저에서 작동하지 않으므로 대신 Babel과 같은 JS 컴파일러를 사용해야합니다. 후드 아래에서 Babel arguments은 for 루프가있는 배열로 변환 됩니다.

function sortArgs(...args) {
  return args.sort();
}

ECMAScript 6을 사용할 수없는 경우 @Jonathan Fingland와 같은 다른 답변을 살펴 보는 것이 좋습니다.

function sortArgs() {
    var args = Array.prototype.slice.call(arguments);
    return args.sort();
}

4

로다시 :

var args = _.toArray(arguments);

행동 :

(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)

생산 :

[2,3]

6
왜 안돼 _.toArray?
Menixator 2016 년

5
그러나 _.toArray더 적절합니다.
Menixator

_.slice가 더 적절하다고 주장합니다.
Hafthor

4

를 사용 Array.from()하여 배열과 같은 객체 (예 arguments:)를 인수로 사용하여 배열로 변환합니다.

(function() {
  console.log(Array.from(arguments));
}(1, 2, 3));

IE 11과 같은 일부 구형 브라우저에서는 작동하지 않으므로 이러한 브라우저를 지원하려면 Babel 을 사용해야합니다 .


3
function sortArg(){
var args = Array.from(arguments); return args.sort();
}

 function sortArg(){
    var args = Array.from(arguments); 
    return args.sort();
    }
 
 console.log(sortArg('a', 'b', 1, 2, '34', 88, 20, '19', 39, 'd', 'z', 'ak', 'bu', 90));


1

또 다른 대답.

흑 마법 주문 사용 :

function sortArguments() {
  arguments.__proto__ = Array.prototype;
  return arguments.slice().sort();
}

Firefox, Chrome, Node.js, IE11은 정상입니다.


6
코드를 완전히 읽을 수 없게하려면 이것이 가장 좋은 해결책입니다. 또한 __proto__더 이상 사용되지 않습니다. MDN 문서를 참조하십시오 .
Michał Perłakowski

1

사용해보십시오 Object.setPrototypeOf()

설명 : 설정 prototypeargumentsArray.prototype

function toArray() {
  return Object.setPrototypeOf(arguments, Array.prototype)
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


설명 :의 각 색인을 가져 와서 arguments항목을 배열의 해당 색인에있는 배열에 놓으 십시오 .

대신 사용할 수 있습니다 Array.prototype.map()

function toArray() {
  return [].map.call(arguments, (_,k,a) => a[k])
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


설명 :의 각 색인을 가져 와서 arguments항목을 배열의 해당 색인에있는 배열에 놓으 십시오 .

for..of 고리

function toArray() {
 let arr = []; for (let prop of arguments) arr.push(prop); return arr
} 

console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))


또는 Object.create()

설명 : 오브젝트를 작성하고의 각 인덱스에서 오브젝트의 특성을 항목으로 설정하십시오 arguments. prototype생성 된 객체 세트Array.prototype

function toArray() {
  var obj = {};
  for (var prop in arguments) {
    obj[prop] = {
      value: arguments[prop],
      writable: true,
      enumerable: true,
      configurable: true
    }
  } 
  return Object.create(Array.prototype, obj);
}

console.log(toArray("abc", 123, {def: 456}, [0, [7, [14]]]))


귀하는 "긴 답변"에 관한 질문에 대한 귀하의 답변이 경고를 만족하는지 여부를 사람들에게 묻었습니다 . 귀하의 답변에 대한 주요 문제 는 여기에 표시된 방법 중 하나를 사용해야 하는 이유를 설명하지 않는 것입니다. 제안 된 솔루션은 모두 허용 된 답변의 솔루션보다 나쁘기 때문에 제안하는 솔루션을 사용할 방법이 없습니다. 예를 들어, 문서에 대한 언급 Object.setPrototypeOf은 "매우 느린 작동"이라고 경고합니다. 왜 지구상에서 이것을 사용 Array.prototype.slice.call합니까?
Louis

@Louis 업데이트 됨 각 접근법에 대한 설명과 함께 답변하십시오. OP의 질문은 "표준 라이브러리를 사용하여 기본 제공 방법이 있습니까?" 하지 "왜 사람은 방법 중 하나를 사용한다" 내장된다? 답변을 게시 한 사용자가 게시 된 솔루션이 OP에 "적합한 지"를 어떻게 정확하게 확인할 수 있습니까? 이것을 결정하는 것이 OP에 달려있는 것처럼 보입니까? 실제로,이 알림 부분은이 사용자에게 관심이있는 것입니다 : "답이 맞는 이유를 설명하십시오" . 이 질문 상태에 제공된 답변 중 "x, y, z"로 인해이 답변이 "올바른"것입니까?
guest271314

내가 설명 한 것은 SO가 일반적으로 어떻게 작동하는지입니다. OP에 대해 게시 된 질문은 주로 OP에 대한 것이 아니라 나중에 질문과 답변을 읽는 수십만 명의 사람들을 위한 것이기 때문에 OP가 한 솔루션이 다른 솔루션보다 더 나은 이유를 알고 싶어하는지 여부는 전적으로 관련이 없습니다 . 또한 답변에 투표하는 사람들은 OP가 만족할만한 것에 따라 투표 할 필요가 없습니다.
Louis

1

깨끗하고 간결한 솔루션은 다음과 같습니다.

function argsToArray() {
  return Object.values(arguments);
}

// example usage
console.log(
  argsToArray(1, 2, 3, 4, 5)
  .map(arg => arg*11)
);

Object.values( )배열로 객체의 값을 반환하고, 이후 arguments객체, 그것은 본질적으로 변환됩니다 arguments배열의 도우미의 모든 기능과 같은과 따라서를 제공, 배열로 map, forEach,filter , 등


0

Benshmarck 3 방법 :

function test()
{
  console.log(arguments.length + ' Argument(s)');

  var i = 0;
  var loop = 1000000;
  var t = Date.now();
  while(i < loop)
  {
      Array.prototype.slice.call(arguments, 0); 
      i++;
  }
  console.log(Date.now() - t);


  i = 0,
  t = Date.now();
  while(i < loop)
  {
      Array.apply(null, arguments);
      i++;
  }
  console.log(Date.now() - t);

  i = 0,
  t = Date.now();
  while(i < loop)
  {
      arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
      i++;
  }
  console.log(Date.now() - t);
}

test();
test(42);
test(42, 44);
test(42, 44, 88, 64, 10, 64, 700, 15615156, 4654, 9);
test(42, 'truc', 44, '47', 454, 88, 64, '@ehuehe', 10, 64, 700, 15615156, 4654, 9,97,4,94,56,8,456,156,1,456,867,5,152489,74,5,48479,89,897,894,894,8989,489,489,4,489,488989,498498);

결과?

0 Argument(s)
256
329
332
1 Argument(s)
307
418
4
2 Argument(s)
375
364
367
10 Argument(s)
962
601
604
40 Argument(s)
3095
1264
1260

즐겨 !


1
같은 것으로 수정을 제안 하시겠습니까 arguments.length == 1?[arguments[0]]:Array.apply(null, arguments);기능을 방지하기 위해 하나의 정수 인자로 호출 dummyFn(3)하고 원인은 결과[,,]
신경 끄시

@Nonemind good job, 편집, 버전이 더 낫습니다.) 그러나 dummyFn(3)이것이 무엇인지 이해하지 못 합니까? 이 기능은 존재하지 않습니다 ...
Matrix

어, 신경 쓰지 마라. 예는 하나의 정수 인수로 함수를 호출하고 고정 크기의 빈 배열을 일으키는 방법을 보여주고 싶다.
nevermind

0

function sortArgs(...args) {
  return args.sort(function (a, b) { return a - b; });
}

document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();


0

나머지 매개 변수는 잘 작동하지만 arguments어떤 이유로 든 계속 사용하려면 다음 을 고려하십시오.

function sortArgs() {
  return [...arguments].sort()
}

[...arguments]에 대한 대안으로 간주 될 수 있으며 Array.from(arguments)완벽하게 작동합니다.

ES7 대안은 배열 이해입니다.

[for (i of arguments) i].sort()

정렬하기 전에 인수를 처리하거나 필터링하려는 경우 가장 쉽습니다.

[for (i of arguments) if (i % 2) Math.log(i)].sort()

0
 function x(){
   var rest = [...arguments]; console.log(rest);return     
   rest.constructor;
 };
 x(1,2,3)

나는 간단한 파괴 기술을 시도


0

Arguments 객체는 함수 본문 내에서만 사용할 수 있습니다. Arguments Object를 배열처럼 인덱싱 할 수 있지만 배열은 아닙니다. 길이 이외의 배열 속성이 없습니다.

// function arguments length 5
function properties(a,b,c,d,e){
var function_name= arguments.callee.name
var arguments_length= arguments.length;
var properties_length=  properties.length; 
var function_from= properties.caller.name;
console.log('I am the function name: '+ function_name);
console.log('I am the function length, I am function spacific: '+ properties_length); 
console.log('I am the arguments length, I am context/excution spacific: '+ arguments_length);
console.log('I am being called From: '+  function_from );
}

// arguments 3
function parent(){
properties(1,2,3);
}

//arguments length 3 because execution spacific
parent();

이 예제에서 볼 수 있듯이 배열처럼 색인을 생성 할 수 있지만 :

function add(){

var sum=0;

for(var i=0; i< arguments.length;i++){

sum = sum + arguments[i];

}

return sum;

}

console.log(add(1,2,3));

그러나 Arguments 객체는 배열이 아니며 length 이외의 다른 속성이 없습니다.

arguments 객체를 Arguments 객체에 액세스 할 수있는 배열로 변환 할 수 있습니다.

함수 본문 내에서 arguments 객체에 액세스 할 수있는 방법은 여러 가지가 있으며 여기에는 다음이 포함됩니다.

  1. Array.prototoype.slice.call 메서드를 호출 할 수 있습니다.

Array.prototype.slice.call (인수)

function giveMeArgs(arg1,arg2){

var args = Array.prototype.slice.call(arguments);
return args
}

console.log( giveMeArgs(1,2));

  1. 배열 리터럴을 사용할 수 있습니다

[] .slice.call (인수).

function giveMeArgs(arg1,arg2){

var args = [].slice.call(arguments);

return args;

}

console.log( giveMeArgs(1,2) );

  1. 당신은 휴식을 사용할 수 있습니다 ...

function giveMeArgs(...args){

return args;

}

console.log(giveMeArgs(1,2))

  1. 당신은 확산을 사용할 수 있습니다 [...]

function giveMeArgs(){

var args = [...arguments];
return args;

}

console.log(giveMeArgs(1,2));

  1. Array.from ()을 사용할 수 있습니다

function giveMeArgs(){

var args = Array.from(arguments);

return args;

}

console.log(giveMeArgs(1,2));


0

인수로 재사용 할 수있는 함수를 만들 수 있습니다. 가장 간단한 함수는 다음과 같습니다.

function sortArgs() {
  return [...arguments].sort();
}

sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];

ES6 이상 에서 스프레드 구문을 사용할 수 있습니다 ...

그러나 ES5 이하 버전과 호환되는 것을 사용하려면을 사용할 수 Array.prototype.slice.call있으므로 코드는 다음과 같습니다.

function sortArgs() {
  return Array.prototype.slice.call(arguments).sort();
}

sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];

Array.from를 들어 인수 를 사용 하거나 반복 하여 새 배열에 할당하는 예제와 같이 다른 방법도 있습니다 .


-2

이것은 매우 오래된 질문이지만 이전 솔루션보다 입력하기가 쉽고 외부 라이브러리에 의존하지 않는 솔루션이 있다고 생각합니다.

function sortArguments() {
  return Array.apply(null, arguments).sort();
}

2
Array.apply양의 정수 인수가 하나만 있으면 작동하지 않습니다. new Array(3)의 배열 길이가 생성 되기 때문 입니다 3. 좀 더 구체적으로 말하자면 결과는 [undefined, undefined, undefined]그렇지 않을 [3]것이다.
inf3rno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.