这个 JS 函数参数语法(具有属性默认值的对象初始值设定项,类似于 rest/spread 参数)是否有名称和效果?



当我发现以前从未见过的语法时,我正在阅读日志记录库源代码,并且在通过解释器评估时似乎没有任何影响:

const createLogger = (title,
{
debugFunction = createDebug(title),
logFunction = console.log
} = {}) => { /* ... */ }
  1. 这种语法叫什么?
  2. 这种语法有什么效果?
  3. 是否可以从函数体中引用对象?

尝试重新创建ts-node输出:

> const testFn2 = (arg1, {dFn = console.debug, lFn = console.log} = {}) => { console.log(arguments) }
undefined
> testFn2(1)
{ '0': 1 }
undefined
> testFn2(1, 2)
{ '0': 1, '1': 2 }
undefined
> testFn2(1, {})
{ '0': 1, '1': {} }
undefined

它是

  • 默认参数值
  • 解构
  • 参数(就像解构赋值一样工作)

以及

  • const(显然)
  • 推断的函数名称(请参阅:如何在 ES2015 中编写命名箭头函数?
  • 箭头函数

。所有这些都是在ES2015中添加的。

它创建一个常量createLogger并将其值设置为名为createLogger的函数,该函数接受两个参数:标题 (title) 和对象。该对象被解构debugFunctionlogFunction参数,如果不存在,则默认为{}

下面是一个更简单的解构参数示例:

function foo({a, b}) {
// Note -----^----^
console.log(a, ",", b);
}
const o = {a: 1, b: 2};
foo(o); // 1 , 2

请注意我们如何用对象调用foo,但foo的代码使用两个参数,其值是从该对象的属性中解构的。

如果我们在没有参数的情况下调用foo,我们会得到一个错误,因为解构尝试访问参数上的属性,而访问undefined上的属性失败:

function foo({a, b}) {
console.log(a, ",", b);
}
foo(); // Fails

如果我们为参数添加默认值,它可以工作:

function foo({a, b} = {a: "default a"}) {
// ----------------^^^^^^^^^^^^^^^^^^^
console.log(a, ",", b);
}
foo(); // default a , undefined (since there's no `b` in the default)

它被称为参数解构与默认值耦合:

let default1 = 1;
let default2 = 2;
const func = ({a = default1, b = default2} = {}) => {
console.log(a);
console.log(b);
}
// Here since no value is specified, the default argument will be {a: 1, b: 2}
func();

您正在查看一个对象析构赋值,在本例中用于初始化局部变量并为其赋值,而无需在函数体中声明它们。这是一种避免编写额外代码的模式;如果你没有析构语法,你基本上会写:

const createLogger = (name, params = {}) => {
let debugFunction = params.debugFunction || createDebug(name);
let logFunction = params.logFunction || console.log;
// do stuff
}

在这一点上,它可能会产生更多的问题,而不是它消除的少量代码所值得的;清晰而不是简洁,尤其是在大型项目中。你可以组合多个三元赋值,而不是写一个if-else块,但这读起来会很糟糕。另一方面,这种风格可能会更加普遍。

最新更新