Деструктуризация параметров (эквивалент двойного сплата 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})
Другие вопросы по тегам