Псевдомасив аргументів - arguments

У деяких мовах програміст може створити дві функції з однаковим ім'ям, але різним набором аргументів, а при виклик інтерпретатор сам вибере потрібну:

Може бути тільки одна функція з ім'ям log, яка викликається з будь-якими аргументами.

А вже всередині вона може подивитися, з чим викликана та по-різному відпрацювати.

Доступ до «зайвих» аргументів

Як отримати значення аргументів, яких немає у списку параметрів?

Доступ до них здійснюється через «псевдомасив» arguments.

Він містить список аргументів за номерами: arguments[0], arguments[1] …, а також властивість length.

Наприклад, виведемо список усіх аргументів:

Усі параметри знаходяться в arguments , навіть якщо вони є у списку. Код вище спрацював би також, якби функція оголошена sayHi (a, b, c).

В результаті зміни arguments впливають на параметри та навпаки.

Якщо ви не використовуєте строгий режим, то щоб змінні не змінювалися «несподівано», рекомендується ніколи не змінювати arguments.

arguments – це не масив

Часта помилка новачків – спроба застосувати методи Array до arguments. Це неможливо:

Справа в тому, що arguments - це не масив Array.

Насправді це звичайний об'єкт, просто ключі числові і є length . На цьому схожість закінчується. Жодних особливих методів у нього немає, і методи масивів він теж не підтримує.

Втім, ніхто не заважає зробити звичайний масив із arguments, наприклад так:

Такі об'єкти іноді називають «колекціями» або «псевдомасивами».

Іноді постає завдання – скопіювати в існуючий об'єкт властивості з однієї чи кількох інших.

Для об'єднання кількох об'єктів в один:

Длястворення копії об'єкта user:

Такий «клон» об'єкта може стати в нагоді там, де хочемо змінювати його властивості, у своїй не чіпаючи вихідний об'єкт user .

У нашій реалізації ми копіюватимемо лише властивості першого рівня, тобто вкладені об'єкти якось особливим чином не обробляються. Втім, її можна розширити.

А ось і реалізація:

Аргументи за замовчуванням через

Якщо функція викликана з меншою кількістю аргументів, ніж зазначено, відсутні аргументи вважаються рівними undefined .

Найчастіше у разі відсутності аргументу ми хочемо надати йому деяке «стандартне» значення або, інакше кажучи, значення «за умовчанням». Це можна зручно зробити за допомогою оператора логічне АБО.

Наприклад, функція showWarning, описана нижче, повинна відображати попередження. І тому вона приймає ширину width , висоту height , заголовок title і вміст contents , але більшість цих аргументів необов'язкова:

Це добре працює у тих ситуаціях, коли «нормальне» значення параметра у логічному контексті на відміну від false . У коді вище, при передачі width = 0 або width = null, оператор АБО замінить його на значення за промовчанням.

А якщо ми хочемо використовувати значення за замовчуванням тільки якщо width === undefined ? В цьому випадку оператор АБО вже не підійде, потрібно поставити явну перевірку:

Застаріла властивість arguments.callee

Ця властивість застаріла, при use strict вона не працює.

Єдина причина, через яку воно тут – це те, що його можна зустріти в старому коді, тому про нього бажано знати.

Сучасна специфікація рекомендує використовувати іменовані функціональні вирази (NFE).

Ці два приклади працюватимуть однаково:

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

arguments.callee.caller

Застаріла властивість arguments.callee.caller зберігає посилання на функцію, яка викликала це.

Ця властивість була в старому стандарті, при use strict вона не працює, як і arguments.callee.

Також раніше існувала більш коротка властивість arguments.caller. Але це вже раритет, він навіть не крос-браузерний. А ось властивість arguments.callee.caller підтримується скрізь, якщо не використаний use strict, тому в старому коді воно трапляється.

У підручнику ми цю властивість також не використовуватимемо.

«Іменовані аргументи»

Іменовані аргументи – альтернативна техніка роботи з аргументами, яка взагалі не використовує arguments.

Деякі мови програмування дозволяють передати параметри якось так: f(width=100, height=200) , тобто за іменами, що не передано, тих аргументів немає. Це дуже зручно у тих випадках, коли аргументів багато, складно запам'ятати їхній порядок і більшість взагалі не треба передавати, за умовчанням підійде.

Така ситуація часто зустрічається у компонентах інтерфейсу. Наприклад, у «меню» може бути маса налаштувань відображення, які можна «підкрутити», але зазвичай потрібно передати всього один-два головні параметри, а решта візьмуться за умовчанням.

Викликати таку функцію дуже легко. Достатньо передати об'єкт аргументів, вказавши у ньому лише потрібні:

Порівняємо це з передачею аргументів через список:

Чи не так, об'єкт - набагато простіше і зрозуміліше?

Ще один бонус крім красивого запису – можливість повторного використання об'єкта аргументів:

  • Повний список аргументів, з якими функція викликана, доступний через arguments .
  • Це псевдомасив, тобто об'єкт,який схожий на масив, у ньому є нумеровані властивості та length, але методів масиву у нього немає.
  • У старому стандарті була властивість arguments.callee з посиланням на поточну функцію, а також властивість arguments.callee.caller , що містить посилання на функцію, яка викликала цю функцію. Ці властивості застаріли, при use strict звернення до них призведе до помилки.
  • Для вказівки аргументів за умовчанням, у випадках, коли вони свідомо не false , зручний оператор .

У тих випадках, коли можливих аргументів багато і особливо коли більшість їх мають значення за замовчуванням, замість роботи з arguments організують передачу даних через об'єкт, який зазвичай називають options .

Можливий і гібридний підхід, при якому перший аргумент є обов'язковим, а другий – options , який містить всілякі додаткові параметри: