网站搜索

javascript - 参数解构(相当于 Python 的双星操作符)


在 Python 中,我可以使用 **(双星号)运算符传递一个键与参数名称匹配的字典:

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)

注意:我正在寻找一种解决方案,不涉及更改 foo 的签名,因为我希望它在两种情况下都能使用(无论是否解构)。所以以下代码应该可以运行:

foo(<magic>args);

foo(123, 456);

附加问题:为什么错误信息是“undefined 不是一个函数”?这里的 undefined 到底是什么?

(正如 @Nina Scholz 在评论中回答的那样,这是因为 ... 需要其参数具有 Symbol.iterator,而对象没有定义这个。)

答案#1

如何在 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));

不过我不敢在生产环境中使用它。

答案#2

你需要用花括号包裹你的 args,并在函数的参数列表中再次包裹。

function foo({a, b}) {
    console.log(a - b)
}

let args = {b: 7, a: 10}

foo({...args})