Чи є спосіб дозволити "необмежену" vars для функції в JavaScript?
Приклад:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Чи є спосіб дозволити "необмежену" vars для функції в JavaScript?
Приклад:
load(var1, var2, var3, var4, var5, etc...)
load(var1)
Відповіді:
Звичайно, просто використовуйте arguments
об'єкт.
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
arguments
це спеціальний "схожий на масив" об'єкт, що означає, що він має довжину, але інших функцій масиву немає. Див developer.mozilla.org/en-US/docs/Web/JavaScript/Reference / ... для отримання додаткової інформації, і ця відповідь: stackoverflow.com/a/13145228/1766230
length
властивість. Сюди входить arguments
об’єкт. Знаючи це, і що метод concat
повертає копію з «масиву» це називається, ми можемо легко перетворити arguments
об'єкт в реальний масив , як це: var args = [].concat.call(arguments)
. Деякі люди вважають за краще використовувати Array.prototype.concat.call
замість цього, але мені подобається []
, вони короткі і солодкі!
[...arguments].join()
У (більшості) останніх веб-переглядачах ви можете приймати змінну кількість аргументів із цим синтаксисом:
function my_log(...args) {
// args is an Array
console.log(args);
// You can pass this array as parameters to another function
console.log(...args);
}
Ось невеликий приклад:
function foo(x, ...args) {
console.log(x, args, ...args, arguments);
}
foo('a', 'b', 'c', z='d')
=>
a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
0: "a"
1: "b"
2: "c"
3: "d"
length: 4
Документація та інші приклади тут: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
Інший варіант - передати свої аргументи в контекстний об'єкт.
function load(context)
{
// do whatever with context.name, context.address, etc
}
і використовувати його так
load({name:'Ken',address:'secret',unused:true})
Це має перевагу в тому, що ви можете додати стільки іменованих аргументів, скільки хочете, і функція може використовувати їх (чи ні), як вважаєте за потрібне.
context
аргумент з кодом і передати його навколо, перш ніж він звикне .
Я погоджуюся з відповіддю Кена як найбільш динамічного, і мені подобається зробити його на крок далі. Якщо це функція, яку ви викликаєте кілька разів з різними аргументами - я використовую дизайн Ken, але потім додаю значення за замовчуванням:
function load(context) {
var defaults = {
parameter1: defaultValue1,
parameter2: defaultValue2,
...
};
var context = extend(defaults, context);
// do stuff
}
Таким чином, якщо у вас є багато параметрів, але не обов'язково їх встановлювати з кожним викликом функції, ви можете просто вказати не за замовчуванням. Для методу розширення ви можете використовувати метод розширення jQuery ( $.extend()
), створити свій власний або скористатися наступним:
function extend() {
for (var i = 1; i < arguments.length; i++)
for (var key in arguments[i])
if (arguments[i].hasOwnProperty(key))
arguments[0][key] = arguments[i][key];
return arguments[0];
}
Це об'єднає контекстний об'єкт із замовчуванням і заповнить будь-які невизначені значення у вашому об'єкті за замовчуванням.
_.defaults()
Метод підкреслення - це дуже приємна альтернатива об'єднанню заданих та типових аргументів.
Переважно використовувати синтаксис параметра відпочинку, як вказав Рамаст.
function (a, b, ...args) {}
Я просто хочу додати трохи приємного властивості аргументу ... args
- Це масив, а не об'єкт, як аргументи. Це дозволяє безпосередньо застосовувати такі функції, як карта чи сортування.
- Він не включає всі параметри, а лише той, який передається від нього далі. Напр. Функція (a, b, ... args) у цьому випадку args містить аргумент 3 до argument.length
Як вже було сказано, ви можете використовувати arguments
об'єкт для отримання змінної кількості параметрів функції.
Якщо ви хочете викликати іншу функцію з тими ж аргументами, використовуйте apply
. Ви навіть можете додавати або видаляти аргументи, перетворюючи arguments
на масив. Наприклад, ця функція вставляє текст перед входом у консоль:
log() {
let args = Array.prototype.slice.call(arguments);
args = ['MyObjectName', this.id_].concat(args);
console.log.apply(console, args);
}
Хоча я загалом погоджуюся, що підхід із названими аргументами є корисним та гнучким (якщо ви не піклуєтесь про порядок, і в цьому випадку аргументи найпростіші), у мене є сумніви щодо вартості підходу mbeasley (з використанням за замовчуванням та розширеннями). Це велика вартість, яку потрібно взяти для витягування значень за замовчуванням. По-перше, параметри за замовчуванням визначаються всередині функції, тому вони перенаселяються під час кожного дзвінка. По-друге, ви можете легко прочитати названі значення та одночасно встановити параметри за замовчуванням, використовуючи || Для отримання цієї інформації не потрібно створювати й об’єднувати ще один новий об’єкт.
function load(context) {
var parameter1 = context.parameter1 || defaultValue1,
parameter2 = context.parameter2 || defaultValue2;
// do stuff
}
Це приблизно однакова кількість коду (може бути трохи більше), але має бути часткою витрат на виконання.
(parameter1=context.parameter1)===undefined && (parameter1=defaultValue1)
або для меншої гучності коду невелика помічна функція, наприклад: function def(providedValue, default) {return providedValue !== undefined ? providedValue : defaultValue;} var parameter1 = def(context.parameter1, defaultValue1)
надайте альтернативні схеми. Однак моя думка все ще стоїть: створення додаткових об'єктів для кожного виклику функції та запуск дорогих циклів для встановлення пари значень за замовчуванням - шалена сума накладних витрат.
Хоча @roufamatic показав використання ключового слова аргументів, а @Ken показав чудовий приклад об’єкта для використання, я не відчуваю, що по-справжньому звертався до того, що відбувається в даному випадку, і може заплутати майбутніх читачів або прищепити погану практику, оскільки явно не вказує функцію. / метод призначений приймати змінну кількість аргументів / параметрів.
function varyArg () {
return arguments[0] + arguments[1];
}
Коли інший розробник переглядає ваш код, дуже легко припустити, що ця функція не приймає параметрів. Особливо, якщо той розробник не прихильний до аргументів ключового слова . Через це є хорошою ідеєю слідувати настановам стилю та бути послідовними. Я буду використовувати Google для всіх прикладів.
Давайте явно констатуємо, що однакова функція має змінні параметри:
function varyArg (var_args) {
return arguments[0] + arguments[1];
}
Можуть бути випадки, коли потрібен об’єкт, оскільки це єдиний затверджений і вважається найкращим методом практики використання даних. Асоціативні масиви нахмурені та відсторонені.
SIDENOTE: Ключове слово аргументи фактично повертає назад об’єкт, використовуючи числа як ключ. Прототиповим успадкуванням є також сімейство об'єктів. Дивіться кінець відповіді щодо правильного використання масиву в JS
У цьому випадку ми можемо також прямо сказати про це. Примітка: ця умова про іменування не надається Google, але є прикладом явного оголошення типу парамнезу. Це важливо, якщо ви хочете створити в своєму коді більш суворий введений зразок.
function varyArg (args_obj) {
return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Це залежить від потреб вашої функції та програми. Якщо, наприклад, ви просто хочете повернути базу значень в ітераційному процесі для всіх переданих аргументів, то, безумовно, дотримуйтесь ключового слова аргументів . Якщо вам потрібне визначення ваших аргументів та відображення даних, тоді об'єктним методом є шлях. Давайте розглянемо два приклади, і тоді ми закінчимо!
function sumOfAll (var_args) {
return arguments.reduce(function(a, b) {
return a + b;
}, 0);
}
sumOfAll(1,2,3); // returns 6
function myObjArgs(args_obj) {
// MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
if (typeof args_obj !== "object") {
return "Arguments passed must be in object form!";
}
return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old
Як було сказано вгорі відповіді, ключове слово аргументи фактично повертає об'єкт. Через це потрібно буде викликати будь-який метод, який ви хочете використовувати для масиву. Приклад цього:
Array.prototype.map.call(arguments, function (val, idx, arr) {});
Щоб уникнути цього, використовуйте параметр "решта":
function varyArgArr (...var_args) {
return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Використовуйте arguments
об'єкт, коли всередині функції, щоб мати доступ до всіх переданих аргументів.
Майте на увазі, що передача Об'єкта з названими властивостями, як запропонував Кен, додає вартість виділення та звільнення тимчасового об'єкта для кожного виклику. Передача звичайних аргументів за значенням або посиланням, як правило, є найбільш ефективною. Для багатьох застосувань, хоча продуктивність не є критичною, але для деяких вона може бути.