解构赋值:参数顺序相互依赖
Destructuring assignment: order of parameters that depend on each other
我以为解构是在检索到所有参数之后执行的,但是我注意到这段代码有效。
function extract(propertyName, { [propertyName]: value }) {
console.log(propertyName, value);
}
extract('property', { property: 'value' });
虽然这个没有。
function extract({ [propertyName]: value }, propertyName) {
console.log(propertyName, value);
}
extract({ property: 'value' }, 'property');
这推翻了我最初的想法,但我找不到任何文档或规范来解释确切的行为。
参数值是按顺序确定的,就像您将每个参数写成自己的let
声明一样,从收到的实际参数中获取值。 (不是它的实际工作方式,这只是一个类比。)
所以你的第一个例子在概念上是这样的:
// ONLY CONCEPTUAL
function extract() {
let propertyName = /*...the first actual argument...*/;
let { [propertyName]: value } = /* ...the second actual argument... */;
console.log(propertyName, value);
}
而你的第二个行为是这样的:
// ONLY CONCEPTUAL
function extract() {
let { [propertyName]: value } = /* ...the first actual argument... */;
let propertyName = /*...the second actual argument...*/;
console.log(propertyName, value);
}
...所以它在“变量”初始化之前尝试使用 propertyName
的值,得到一个错误。 (因为参数表达式是在 ES2015 中添加的,所以它们使用 let
而不是 var
语义。)
另一种看待它的方式是,如果将整个参数列表视为迭代器解构的内容,它的工作方式完全相同。这样想,你的第一个例子是:
// v−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−v−−−−− iterable destructuring
let [propertyName, { [propertyName]: value }] = /* an iterable for the actual arguments */;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^−−−−−− parameter list
FunctionDeclarationInstantiation and IteratorBindingInitialization 部分的规范中对此进行了介绍。
请注意,这实际上与解构没有任何关系,只是当函数代码为 运行 时参数值如何分配给参数。例如,如果您尝试在较早参数的默认值表达式中使用较晚的参数名称,它会因同样的原因而失败。
我以为解构是在检索到所有参数之后执行的,但是我注意到这段代码有效。
function extract(propertyName, { [propertyName]: value }) {
console.log(propertyName, value);
}
extract('property', { property: 'value' });
虽然这个没有。
function extract({ [propertyName]: value }, propertyName) {
console.log(propertyName, value);
}
extract({ property: 'value' }, 'property');
这推翻了我最初的想法,但我找不到任何文档或规范来解释确切的行为。
参数值是按顺序确定的,就像您将每个参数写成自己的let
声明一样,从收到的实际参数中获取值。 (不是它的实际工作方式,这只是一个类比。)
所以你的第一个例子在概念上是这样的:
// ONLY CONCEPTUAL
function extract() {
let propertyName = /*...the first actual argument...*/;
let { [propertyName]: value } = /* ...the second actual argument... */;
console.log(propertyName, value);
}
而你的第二个行为是这样的:
// ONLY CONCEPTUAL
function extract() {
let { [propertyName]: value } = /* ...the first actual argument... */;
let propertyName = /*...the second actual argument...*/;
console.log(propertyName, value);
}
...所以它在“变量”初始化之前尝试使用 propertyName
的值,得到一个错误。 (因为参数表达式是在 ES2015 中添加的,所以它们使用 let
而不是 var
语义。)
另一种看待它的方式是,如果将整个参数列表视为迭代器解构的内容,它的工作方式完全相同。这样想,你的第一个例子是:
// v−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−v−−−−− iterable destructuring
let [propertyName, { [propertyName]: value }] = /* an iterable for the actual arguments */;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^−−−−−− parameter list
FunctionDeclarationInstantiation and IteratorBindingInitialization 部分的规范中对此进行了介绍。
请注意,这实际上与解构没有任何关系,只是当函数代码为 运行 时参数值如何分配给参数。例如,如果您尝试在较早参数的默认值表达式中使用较晚的参数名称,它会因同样的原因而失败。