- JavaScript: Convert arguments to Array
- Псевдомассив аргументов «arguments»
- Доступ к «лишним» аргументам
- arguments – это не массив
- Пример: копирование свойств copy(dst, src1, src2. )
- Аргументы по умолчанию через ||
- Устаревшее свойство arguments.callee
- arguments.callee.caller
- «Именованные аргументы»
- Итого
- How to convert arguments object to an array in JavaScript
- You might also like.
JavaScript: Convert arguments to Array
All JavaScript functions have a local variable called arguments , which is a list of arguments that were passed to the executing function. The first argument can be accessed as arguments[0] , the second one as arguments[1] etc. To find out the numbers of arguments you can do arguments.length .
You can see arguments is a lot like an array. I say it is a lot like an array because it actually is not an array at all, it is an array-like object. You can access the items using a numerical index and it has a length property, but it is not an array.
arguments is actually structured like this:
As long as you are limited to accessing the the items using an index and finding out the length of the arguments, you are a happy coder, but you have a problem when you want to call true array methods on arguments . If you plan on using arguments like an array in more than once instance, it best to convert it into an real array. Here is the way to do it:
arguments = Array.prototype.slice.call(arguments);
Now arguments is a real array and you can call all the array methods like slice() , splice() , map() etc. You may see code examples doing Array.prototype.slice.call(arguments, 0) instead of Array.prototype.slice.call(arguments) , they are one and the same — when you don’t pass any index to slice() , it is understood as 0.
In case you are interested in how the solution works, we used JavaScript’s functional programming function call() to assign Array ‘s slice() method temporarily to arguments and created an array containing the items of the argument array-like object.
Any method of converting arguments to array using loop should be avoided, because it is inefficient and way slower.
You can see the above concepts demonstrated in the editable example below:
Псевдомассив аргументов «arguments»
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
В JavaScript любая функция может быть вызвана с произвольным количеством аргументов.
function go(a,b) < alert("a="+a+", b="+b); >go(1); // a=1, b=undefined go(1,2); // a=1, b=2 go(1,2,3); // a=1, b=2, третий аргумент не вызовет ошибку
В некоторых языках программист может создать две функции с одинаковым именем, но разным набором аргументов, а при вызове интерпретатор сам выберет нужную:
function log(a) < . >function log(a, b, c) < . >log(a); // вызовется первая функция log(a, b, c); // вызовется вторая функция
Это называется «полиморфизмом функций» или «перегрузкой функций». В JavaScript ничего подобного нет.
Может быть только одна функция с именем log , которая вызывается с любыми аргументами.
А уже внутри она может посмотреть, с чем вызвана и по-разному отработать.
В примере выше второе объявление log просто переопределит первое.
Доступ к «лишним» аргументам
Как получить значения аргументов, которых нет в списке параметров?
Доступ к ним осуществляется через «псевдо-массив» arguments.
Он содержит список аргументов по номерам: arguments[0] , arguments[1] …, а также свойство length .
Например, выведем список всех аргументов:
function sayHi() < for (var i = 0; i < arguments.length; i++) < alert( "Привет, " + arguments[i] ); >> sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Привет, Пятачок'
Все параметры находятся в arguments , даже если они есть в списке. Код выше сработал бы также, будь функция объявлена sayHi(a,b,c) .
В старом стандарте JavaScript псевдо-массив arguments и переменные-параметры ссылаются на одни и те же значения.
В результате изменения arguments влияют на параметры и наоборот.
В современной редакции стандарта это поведение изменено. Аргументы отделены от локальных переменных:
Если вы не используете строгий режим, то чтобы переменные не менялись «неожиданно», рекомендуется никогда не изменять arguments .
arguments – это не массив
Частая ошибка новичков – попытка применить методы Array к arguments . Это невозможно:
Дело в том, что arguments – это не массив Array .
В действительности, это обычный объект, просто ключи числовые и есть length . На этом сходство заканчивается. Никаких особых методов у него нет, и методы массивов он тоже не поддерживает.
Впрочем, никто не мешает сделать обычный массив из arguments , например так:
var args = []; for (var i = 0; i
Такие объекты иногда называют «коллекциями» или «псевдомассивами».
Пример: копирование свойств copy(dst, src1, src2. )
Иногда встаёт задача – скопировать в существующий объект свойства из одного или нескольких других.
Напишем для этого функцию copy . Она будет работать с любым числом аргументов, благодаря использованию arguments .
copy(dst, src1, src2…) Копирует свойства из объектов src1, src2. в объект dst . Возвращает получившийся объект.
- Для объединения нескольких объектов в один:
var vasya = < age: 21, name: 'Вася', surname: 'Петров' >; var user = < isAdmin: false, isEmailConfirmed: true >; var student = < university: 'My university' >; // добавить к vasya свойства из user и student copy(vasya, user, student); alert( vasya.isAdmin ); // false alert( vasya.university ); // My university
// скопирует все свойства в пустой объект var userClone = copy(<>, user);
function copy() < var dst = arguments[0]; for (var i = 1; i < arguments.length; i++) < var arg = arguments[i]; for (var key in arg) < dstJavascript arguments в массив = argJavascript arguments в массив; >> return dst; >
Здесь первый аргумент copy – это объект, в который нужно копировать, он назван dst . Для упрощения доступа к нему можно указать его прямо в объявлении функции:
function copy(dst) < // остальные аргументы остаются безымянными for (var i = 1; i < arguments.length; i++) < var arg = arguments[i]; for (var key in arg) < dstJavascript arguments в массив = argJavascript arguments в массив; >> return dst; >
Аргументы по умолчанию через ||
Если функция вызвана с меньшим количеством аргументов, чем указано, то отсутствующие аргументы считаются равными undefined .
Зачастую в случае отсутствия аргумента мы хотим присвоить ему некоторое «стандартное» значение или, иначе говоря, значение «по умолчанию». Это можно удобно сделать при помощи оператора логическое ИЛИ || .
Например, функция showWarning , описанная ниже, должна показывать предупреждение. Для этого она принимает ширину width , высоту height , заголовок title и содержимое contents , но большая часть этих аргументов необязательна:
function showWarning(width, height, title, contents) < width = width || 200; // если не указана width, то width = 200 height = height || 100; // если нет height, то height = 100 title = title || "Предупреждение"; //. >
Это отлично работает в тех ситуациях, когда «нормальное» значение параметра в логическом контексте отлично от false . В коде выше, при передаче width = 0 или width = null , оператор ИЛИ заменит его на значение по умолчанию.
А что, если мы хотим использовать значение по умолчанию только если width === undefined ? В этом случае оператор ИЛИ уже не подойдёт, нужно поставить явную проверку:
function showWarning(width, height, title, contents) < if (width === undefined) width = 200; if (height === undefined) height = 100; if (title === undefined) title = "Предупреждение"; //. >
Устаревшее свойство arguments.callee
Это свойство устарело, при use strict оно не работает.
Единственная причина, по которой оно тут – это то, что его можно встретить в старом коде, поэтому о нём желательно знать.
Современная спецификация рекомендует использовать именованные функциональные выражения (NFE).
В старом стандарте JavaScript объект arguments не только хранил список аргументов, но и содержал в свойстве arguments.callee ссылку на функцию, которая выполняется в данный момент.
Эти два примера будут работать одинаково:
// подвызов через NFE var factorial = function f(n) < return n==1 ? 1 : n*f(n-1); >; // подвызов через arguments.callee var factorial = function(n) < return n==1 ? 1 : n*arguments.callee(n-1); >;
В учебнике мы его использовать не будем, оно приведено для общего ознакомления.
arguments.callee.caller
Устаревшее свойство arguments.callee.caller хранит ссылку на функцию, которая вызвала данную.
Это свойство было в старом стандарте, при use strict оно не работает, как и arguments.callee .
Также ранее существовало более короткое свойство arguments.caller . Но это уже раритет, оно даже не кросс-браузерное. А вот свойство arguments.callee.caller поддерживается везде, если не использован use strict , поэтому в старом коде оно встречается.
f1(); function f1() < alert( arguments.callee.caller ); // null, меня вызвали из глобального кода f2(); >function f2() < alert( arguments.callee.caller ); // f1, функция, из которой меня вызвали f3(); >function f3() < alert( arguments.callee.caller ); // f2, функция, из которой меня вызвали >
В учебнике мы это свойство также не будем использовать.
«Именованные аргументы»
Именованные аргументы – альтернативная техника работы с аргументами, которая вообще не использует arguments .
Некоторые языки программирования позволяют передать параметры как-то так: f(width=100, height=200) , то есть по именам, а что не передано, тех аргументов нет. Это очень удобно в тех случаях, когда аргументов много, сложно запомнить их порядок и большинство вообще не надо передавать, по умолчанию подойдёт.
Такая ситуация часто встречается в компонентах интерфейса. Например, у «меню» может быть масса настроек отображения, которые можно «подкрутить» но обычно нужно передать всего один-два главных параметра, а остальные возьмутся по умолчанию.
В JavaScript для этих целей используется передача аргументов в виде объекта, а в его свойствах мы передаём параметры.
function showWarning(options) < var width = options.width || 200; // по умолчанию var height = options.height || 100; var contents = options.contents || "Предупреждение"; // . >
Вызвать такую функцию очень легко. Достаточно передать объект аргументов, указав в нем только нужные:
Сравним это с передачей аргументов через список:
showWarning(null, null, "Предупреждение!"); // мысль программиста "а что это за null, null в начале? ох, надо глядеть описание функции"
Не правда ли, объект – гораздо проще и понятнее?
Ещё один бонус кроме красивой записи – возможность повторного использования объекта аргументов:
var opts = < width: 400, height: 200, contents: "Текст" >; showWarning(opts); opts.contents = "Другой текст"; showWarning(opts); // вызвать с новым текстом, без копирования других аргументов
Именованные аргументы применяются во многих JavaScript-фреймворках.
Итого
- Полный список аргументов, с которыми вызвана функция, доступен через arguments .
- Это псевдомассив, то есть объект, который похож на массив, в нём есть нумерованные свойства и length , но методов массива у него нет.
- В старом стандарте было свойство arguments.callee со ссылкой на текущую функцию, а также свойство arguments.callee.caller , содержащее ссылку на функцию, которая вызвала данную. Эти свойства устарели, при use strict обращение к ним приведёт к ошибке.
- Для указания аргументов по умолчанию, в тех случаях, когда они заведомо не false , удобен оператор || .
В тех случаях, когда возможных аргументов много и, в особенности, когда большинство их имеют значения по умолчанию, вместо работы с arguments организуют передачу данных через объект, который как правило называют options .
Возможен и гибридный подход, при котором первый аргумент обязателен, а второй – options , который содержит всевозможные дополнительные параметры:
function showMessage(text, options) < // показать сообщение text, настройки показа указаны в options >
How to convert arguments object to an array in JavaScript
The arguments object is an array-like object accessible inside all non-arrow functions that represents the values of the arguments passed to that function. You can use numerical indexes to access the values of arguments from the arguments object. For example, the first argument can be accessed as arguments[0] , the second argument can be accessed as arguments[1] , and so on.
The arguments object is a lot like an array, but it is not a real array. Although it has the length property, you can not use the common array methods like map() , slice() , and filter() on it.
There are multiple ways to convert an arguments object to a true Array object.
The rest parameter syntax was introduced in ES6 to represent an unspecified number of arguments as an array. To use rest parameters, you can prefix the function’s last parameter with . (spread operator). It will convert all remaining user-supplied arguments into a standard JavaScript array. Since the rest parameter is a real Array instance, unlike the arguments object, you do not need to perform any conversion:
const sort = (. numbers) => return numbers.sort((a, b) => a - b) > sort(1, 4, 5, 2) // [ 1, 2, 4, 5 ]
Another way to convert the arguments object to an array in ES6 is by using the Array.from() method. This method converts an array-like or iterable object into an Array instance:
function sort() return Array.from(arguments).sort((a, b) => a - b) > sort(1, 4, 5, 2) // [ 1, 2, 4, 5 ]
Finally, the last method to convert an arguments object to an array is the Array.prototype.slice() method. Much like converting a NodeList to an array, the Array.slice() method takes in the arguments object and transforms it into an actual array:
function sort() const args = Array.prototype.slice.call(arguments) return args.sort((a, b) => a - b) > const sorted = sort(1, 4, 5, 2) console.log(sorted) // [ 1, 2, 4, 5 ]
const args = [].slice.call(arguments)
The Array.prototype.slice.call() works in all modern and old browsers, including IE 6+. You should use this approach if you want to support old browsers. To learn more about JavaScript arrays and how to store multiple pieces of information in one single variable, read this guide. ✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.