为什么{a:y = 1} = {b:2}有效,而{a:1} = {b:2}是SyntaxError?

bar*_*occ 6 javascript

我不明白为什么这两个JS表达式不相等

为了更好地使用JS,我正在尝试一些JavaScript表达式。这是我的最新发现:

{ a: y = 1 } = { b: 2 } // {b: 2}
{ a: 1     } = { b: 2 } // Uncaught SyntaxError: Unexpected token =
Run Code Online (Sandbox Code Playgroud)

有人可以帮我理解吗?

for*_*d04 3

首先,这不是在没有声明的情况下解构赋值的正确语法。

当使用没有声明的对象字面量解构赋值时,赋值语句周围需要括号 (...)。

{a, b} = {a: 1, b: 2} 不是有效的独立语法,因为左侧的 {a, b} 被视为块而不是对象文字。

您可以编写以下内容之一:

// assignment with declaration
const { a: y = 1 } = { b: 2 }
const { a: 1     } = { b: 2 }

// without declaration
({ a: y = 1 } = { b: 2 })
({ a: 1     } = { b: 2 })
Run Code Online (Sandbox Code Playgroud)

const { a: y = 1 } = { b: 2 }将创建一个y值为 的新变量1a无法从解构{ b: 2 },但默认值为1。a还将被分配给新的变量名称y

({ a: 1 } = { b: 2 })不起作用,因为a无法解构并且没有默认值。因此,你得到SyntaxError: invalid destructuring target.

更新 - 更多背景信息:

解构赋值是一个表达式。如果您{ a: y = 1 } = { b: 2 }在浏览器控制台中键入,您将得到SyntaxError: expected expression, got '=',因此代码不能解释为表达式 - 相反,它被视为一个(零个或多个语句)。有一个解决方案 - 您可以使用括号来强制执行显式表达式上下文。这就是原因,为什么({ a: y = 1 } = { b: 2 })有效。您还可以console.log({ a: y = 1 } = { b: 2 })在浏览器控制台中键入,因为引擎可以确定函数参数是一个表达式。

另请看一下这段引用

[...] 对于表达式语句,存在重叠:在那里,表达式出现在语句上下文中。为了防止歧义,JavaScript 语法禁止表达式语句以大括号或关键字 function 开头。

那么,如果您想编写以这两个标记之一开头的表达式语句,该怎么办?您可以将其放在括号中,这不会更改其结果,但确保它出现在仅表达式上下文中。

更新 2 - 关于浏览器/JavaScript 引擎的差异

{ a: y = 1 } = { b: 2 }当您在控制台中键入时,您会得到以下输出:

  • 火狐浏览器:SyntaxError: expected expression, got '='
  • Chrome 和 Node(均为 V8 引擎):{b: 2}

呃,这是为什么?Chrome/Node 的输出表明代码确实被控制台计算为表达式,因为它计算出等号( quote{b:2右侧的值 } :

[...] 从概念上讲,有两种类型的表达式:有副作用的表达式(例如:为变量赋值的表达式)和在某种意义上评估并因此解析为值的表达式。

表达式 x = 7 是第一种类型的示例。该表达式使用 = 运算符将值 7 赋给变量 x。该表达式本身的计算结果为 7。

如果您eval('{ a: y = 1 } = { b: 2 }')在 Chrome/Node 控制台中输入,您将得到Uncaught SyntaxError: Unexpected token '=',这是正确的行为!eval('var { a: y = 1 } = { b: 2 }')照常工作。我认为,这是一个强烈的迹象,控制台本身积极尝试将代码解释为此处的表达式,并且V8 引擎正常工作而没有错误。

  • 问题是为什么第一个不抛出错误而第二个却抛出错误 (2认同)