Как преобразовать объект "arguments" в массив в 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. Есть ли встроенный способ сделать это, используя стандартную библиотеку?

Ответы

Ответ 1

ES6 с использованием параметров отдыха

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

Параметры останова

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

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

Ответ 2

Также стоит ссылаться на эту страницу вики-страницы Bluebird promises, которая показывает, как управлять объектом arguments в массиве таким образом, чтобы функция оптимизировалась под движком JavaScript 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);. Автор также показывает, как шаг сборки может помочь уменьшить многословие.

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

Я рекомендую использовать 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();
}

Ответ 8

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

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

Ответ 9

Lodash:

var args = _.toArray(arguments);

в действии:

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

дает:

[2,3]

Ответ 10

В ECMAScript 6 нет необходимости использовать уродливые хаки, например Array.prototype.slice(). Вместо этого вы можете использовать синтаксис распространения (...).

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

Ответ 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));

Ответ 12

Другой ответ.

Использовать Черные магические заклинания:

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

Firefox, Chrome, Node.js, IE11 в порядке.

Ответ 13

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

Объяснение: Установите prototype из arguments в Array.prototype

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

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

Ответ 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

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

Ответ 15

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

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

Ответ 16

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

Ответ 17

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

Я пробовал простую деструктивную технику

Ответ 18

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

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

Ответ 19

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

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

Ответ 20

const array = [...arguments];
const sortArray = [...arguments].sort()

Ответ 21

Я не могу комментировать выше, так что... Я попробовал это:

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

var aaa = doesntLeakArguments().join();

Почему значение aaa "[Аргументы объекта]"?

Ответ 22

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

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