ES6 中的函数参数定义

Function parameter definitions in ES6

我确信这相对简单,而且我遗漏了一些明显的东西。我正在阅读 Mozilla's tutorials on ES6, and their chapter on destructuring 包含以下模式:

FUNCTION PARAMETER DEFINITIONS

As developers, we can often expose more ergonomic APIs by accepting a single object with multiple properties as a parameter instead of forcing our API consumers to remember the order of many individual parameters. We can use destructuring to avoid repeating this single parameter object whenever we want to reference one of its properties:

function removeBreakpoint({ url, line, column }) {   
    // ... 
}

This is a simplified snippet of real world code from the Firefox DevTools JavaScript debugger (which is also implemented in JavaScript—yo dawg). We have found this pattern particularly pleasing.

我不明白这与解构有什么关系。您是否允许将对象以任意顺序传递给此函数,只要它包含所有项目,即 { line: 10, column: 20, url: 'localhost' }

如果是这样,与

之类的东西相比有什么好处
 function removeBreakpoint(params) {   
     // ... 
 }

其中 params 是具有 urllinecolumn 的对象?这个想法只是您通过显式定义强制 Javascript 在解构上下文中使用时验证函数的参数吗?

What I don't understand is how this relates to destructuring.

removeBreakpoint中,您可以直接使用urllinecolumn。当使用选项对象调用 removeBreakpoint 时,就会发生解构;该对象的匹配属性被分解为单独的参数。

Is the idea that you permit the ability to pass an object into this function that can be in arbitrary order as long as it contains all items, i.e. { line: 10, column: 20, url: 'localhost' }?

是的,但不必包含所有项目;如果不存在,则由于参数是从不存在的对象 属性 初始化的,因此参数为 undefined(除非指定了默认值)。

演示解构的简单示例(Live Copy with ES5 translation on Babel 的 REPL):

"use strict";
function removeBreakpoint({ url, line, column }) {   
    console.log("removeBreakpoint:");
    console.log("url: " + url);
    console.log("line: " + line);
    console.log("column: " + column);
}
removeBreakpoint({
  url: "the url",
  line: "the line",
  column: "the column"
});
removeBreakpoint({
  url: "the url",
  line: "the line"
});

输出:

removeBreakpoint:
url: the url
line: the line
column: the column
removeBreakpoint:
url: the url
line: the line
column: undefined

If so, what is the benefit over something like

function removeBreakpoint(params) {   
   // ... 
}

where params is an object with url, line, and column?

语法糖。接受选项对象的新语法更加简洁和声明,自动化了一个通用模式。当您将它与默认值 (Live Copy) 结合使用时,这一点尤为明显:

"use strict";
function removeBreakpoint(
    {                               // <= { starts destructuring arg
        url = "url default",        // <= Default for `url`
        line = "line default",      // <= ...for `line`
        column = "column default"   // <= ...for `column`
    }                               // <= } ends destructuring arg
    = {}                            // <= Default for the options object iself
) {                                 //    (see notes after the code block)
    console.log("removeBreakpoint:");
    console.log(url);
    console.log(line);
    console.log(column);
}
removeBreakpoint({
  url: "the url",
  line: "the line",
  column: "the column"
});
removeBreakpoint({
  url: "the url",
  line: "the line"
});
removeBreakpoint();

输出:

removeBreakpoint:
the url
the line
the column
removeBreakpoint:
the url
the line
column default
removeBreakpoint:
url default
line default
column default

在上面,甚至选项对象本身也是可选的,这就是最后一个调用有效的原因:

removeBreakpoint();

如果我们没有为选项对象本身提供默认值,该调用将失败,因为我们将尝试读取 undefined 的 属性 url。有时您想要那个,所以您会关闭整个选项。其他时候你不会。


旁注:默认部分选项对象以及单独的整个选项对象的能力导致了一个有趣的情况,你可以有不同的默认值取决于是否给出了一个选项对象但没有特定的选项 vs. 没有给出任何选项对象,全部以声明方式完成:Live Copy

"use strict";
function test(
    num,
    {
        foo = "foo default",
        bar = "options given without bar"
    } = {bar: "options not given at all"}
) {
    console.log(num + ": foo = " + foo + ", bar = " + bar);
}
test(1, {foo: "foo value", bar: "options given with bar"});
test(2, {bar: "options given with bar"});
test(3, {});
test(4);

输出:

1: foo = foo value, bar = options given with bar
2: foo = foo default, bar = options given with bar
3: foo = foo default, bar = options given without  bar
4: foo = foo default, bar = options not given at all