Деструктуризация параметров (эквивалент двойного сплата Python)
В Python я могу передать dict, чьи ключи соответствуют именам параметров с **
(двойной знак) оператор:
def foo(a, b):
print (a - b)
args = {'b': 7, 'a': 10}
foo(**args) # prints 3
Как сделать то же самое в ES6? Это не работает:
function foo(a, b) {
console.log(a - b)
}
args = {b: 7, a: 10}
foo(...args)
NB: я ищу решение, которое не включает изменение подписи foo
потому что я хочу, чтобы он использовался в любом случае (с деструктурой и без нее). Поэтому должно работать следующее:
foo(<magic>args);
foo(123, 456);
Бонусный вопрос: почему сообщение об ошибке "undefined не является функцией"? Что именно здесь не определено?
(Как ответила @Nina Scholz в комментариях, это потому, что ...
требует своего аргумента, чтобы иметь Symbol.iterator
, который не определен для объектов).
2 ответа
Как сделать то же самое в ES6?
В JS нет именованных аргументов, только позиционные. Таким образом, ответ: вы не можете.
То, что вы можете сделать, это либо эмулировать именованные аргументы посредством передачи объекта, как предложено @Andy.
function foo({ a, b }) {
console.log(a - b);
}
let args = { b: 7, a: 10 };
foo(args);
Или вы могли бы сделать args
быть массивом, так что вы можете разбить его на позиционные аргументы.
function foo(a, b) {
console.log(a - b);
}
let args = [10, 7];
foo(...args);
Ладно-ладно, просто ради аргумента: можно написать функцию, которая будет извлекать параметры foo
и дать свойства args
в требуемом порядке.
function * yolo(args, fn) {
const names = fn.toString().match(/\(.+\)/)[0]
.slice(1, -1).split(',')
.map(x => x.trim());
while (names.length) {
yield args[names.shift()];
}
}
function foo(a, b) {
console.log(a - b);
}
const args = { b: 7, a: 10 };
foo(...yolo(args, foo));
Я бы не посмел использовать его в производстве.
Вы должны обернуть args
в фигурных скобках и снова в списке аргументов для функции.
function foo({a, b}) {
console.log(a - b)
}
let args = {b: 7, a: 10}
foo({...args})