Как преобразовать объект "аргументы" в массив в JavaScript?

на arguments объект в JavaScript-это странная бородавка-это действует так же, как массив, в большинстве ситуаций, но это не на самом деле объект массива. Так как это действительно что-то совсем другое, он не имеет полезных функций от Array.prototype как forEach, sort, filter и map.

тривиально легко построить новый массив из объекта arguments с простым циклом for. Например, эта функция сортирует аргументы:

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

однако это довольно жалкая вещь, чтобы просто получить доступ к чрезвычайно полезным функциям массива JavaScript. Есть ли встроенный способ сделать это с помощью стандартной библиотеки?

20 ответов


ES6 с использованием параметров rest

если вы можете использовать ES6, вы можете использовать:

Параметры Остальные

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

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

как вы можете прочитать в ссылке

синтаксис параметра rest позволяет нам представлять неопределенное количество аргументов в виде массива.

Если вам интересно о ... синтаксис, это называется Распространение Оператор а можно подробнее здесь.

ES6 с использованием массива.от ()

используя массив.от:

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

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

Array.from просто преобразуйте массивные или итерационные объекты в экземпляры массива.



в ES5

вы можете просто использовать Array ' s slice функция на объекте arguments, и она преобразует его в стандартный массив JavaScript. Вам просто нужно будет ссылаться на него вручную через прототип Array:

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

почему это работает? Ну, вот отрывок из сама документация ECMAScript 5:

Примечание: элемент slice функция намеренно универсальна; она не требует, чтобы ее этой значение-объект массива. Поэтому его можно перенести к другим видам объектов для использовать как метод. Ли slice функция может быть успешно применена к объекту хоста, зависящему от реализации.

таким образом, slice работает на все, что имеет length свойство, которое arguments удобно ли.


если Array.prototype.slice слишком много для вас, вы можете немного сократить его, используя литералы массива:

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

тем не менее, я склонен чувствовать, что прежняя версия более явная, поэтому я бы предпочел ее вместо. Злоупотребление литеральной нотацией массива кажется хакерским и выглядит странно.


стоит ссылка это Bluebird обещает библиотека вики-страницы это показывает, как управлять arguments объект в массив таким образом, что делает функция оптимизируется под V8 JavaScript engine:

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);. Автор также показывает, как шаг сборки может помочь уменьшить многословие.


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

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

некоторые методы массива намеренно не требуют, чтобы целевой объект был фактическим массивом. Они требуют только, чтобы цель имела свойство с именем длина и индексы (которые должны быть нулевыми или большими целыми числами).

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

использование:

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 версия (медленнее, быстрее, чем slice):

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();
}

Если вы используете jQuery, на мой взгляд, следующее намного проще запомнить:

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

вот ориентир несколько методов преобразования аргументов в массив.

Что касается меня, лучшим решением для небольшого количества аргументов является:

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(); }

Я рекомендую использовать ECMAScript 6 распространение оператор, который свяжет конечные параметры в массив. С помощью этого решения вам не нужно прикасаться к arguments объект и ваш код будут упрощены. Недостатком этого решения является то, что оно не работает в большинстве браузеров, поэтому вместо этого вам придется использовать JS-компилятор, такой как Babel. Под капотом 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();
}

Лодашь:

var args = _.toArray(arguments);

действие:

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

выдает:

[2,3]

использовать Array.from(), который принимает объект типа массива (например,arguments) в качестве аргумента и преобразует его в массив:

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

обратите внимание, что он не работает в некоторых старых браузерах, таких как IE 11, поэтому, если вы хотите поддерживать эти браузеры, вы должны использовать Бабель.


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));

в 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, поэтому, если вы хотите поддерживать эти браузеры, вы должны использовать Бабель.


Другого Ответа.

Используйте Заклинания Черной Магии:

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

Firefox, Chrome, Узел.js, IE11 в порядке.


попробуйте использовать Object.setPrototypeOf()

Объяснение: Set prototype of arguments to Array.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; set 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]]]))

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

наслаждайтесь !


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

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

хотя остальные хорошо работают, если вы хотите продолжать использовать 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()

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

Я пробовал простой метод разрушения


объект arguments доступен только внутри тела функции. Хотя объект Arguments можно индексировать как массив, он не является массивом. Он не имеет никаких свойств массива, кроме length.

// 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 не является массивом и не имеет никаких других свойств, кроме длина.

вы можете преобразовать объект arguments в массив, в котором вы можете получить доступ к объекту Arguments.

есть много способов доступа к объекту arguments внутри тела функции, и они включают в себя:

  1. вы можете вызвать массив.prototoype.ломтик.вызов метода.

массив.прототип.ломтик.вызов(аргументы)

function giveMeArgs(arg1,arg2){

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

console.log( giveMeArgs(1,2));
  1. вы можете использовать литерал массива

[].ломтик.вызов(аргументы).

function giveMeArgs(arg1,arg2){

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

return args;

}

console.log( giveMeArgs(1,2) );
  1. вы можете использовать REST ...

function giveMeArgs(...args){

return args;

}

console.log(giveMeArgs(1,2))
  1. вы можете использовать spread [...]

function giveMeArgs(){

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

}

console.log(giveMeArgs(1,2));
  1. вы можете использовать массив.от ()

function giveMeArgs(){

var args = Array.from(arguments);

return args;

}

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

вы можете создать многоразовую функцию, чтобы сделать это с любыми аргументами, самый простой из них-что-то вроде этого:

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

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

синтаксис Spread можно использовать в ЕС6 и выше...

но если вы хотите использовать что-то совместимое с в 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 или петля через аргументы и назначьте их в новый массив...


это очень старый вопрос, но я думаю, что у меня есть решение, которое немного легче ввести, чем предыдущие решения, и не полагается на внешние библиотеки:

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