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

时间:2019-09-04 08:44:43

标签: javascript

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

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

{ a: y = 1 } = { b: 2 } // {b: 2}
{ a: 1     } = { b: 2 } // Uncaught SyntaxError: Unexpected token =

有人可以帮助我理解吗?

3 个答案:

答案 0 :(得分:3)

首先,这不是destructuring assignments without declarations的正确语法。

  

使用不带声明的对象文字解构分配时,需要在赋值语句周围加上括号(...)。

     

{a,b} = {a:1,b:2}是无效的独立语法,因为左侧的{a,b}被认为是一个块,而不是对象文字。< / p>

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

// 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 })

const { a: y = 1 } = { b: 2 }将创建一个值为y的新变量1a不能是{ b: 2 }中的destructured,而是default value为1。a也将是assigned to a new variable名称y

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

更新-其他背景:

destructuring assignmentexpression。如果在浏览器控制台中键入{ a: y = 1 } = { b: 2 },则会得到SyntaxError: expected expression, got '=',因此代码无法解释为表达式-而是将其视为block(零个或多个语句)。有一个解决方案-您可以使用括号来强制使用显式表达式上下文。这就是({ a: y = 1 } = { b: 2 })起作用的原因。您还可以 在浏览器控制台中输入console.log({ a: y = 1 } = { b: 2 }),因为引擎可以确定function参数为表达式。

也可以看看这个quote

  

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

     

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

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

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

  • Firefox:SyntaxError: expected expression, got '='
  • Chrome和Node(均为V8引擎):{b: 2}

Du,为什么呢? Chrome / Node的输出表明该代码确实已被控制台评估为表达式,因为它的结果等于等号(quote)右侧的值{b:2}:

  

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

     

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

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

答案 1 :(得分:1)

这取决于您如何运行。如果这个东西在顶层,如

{ a: 1 } = { b: 2 }

错误是“意外的=“,因为{a:1}是一个块,而不是对象(例如,Differentiate a block from an object initializer)。

如果用作表达式

({ a: 1 } = { b: 2 })

错误(至少在V8中)是“无效的销毁分配目标”。

此:

let { a: 1 } = { b: 2 };

会产生“意外数字”,尽管与上面的错误相同:您不能有一个名为“ 1”的变量。

最后,如果您在控制台中运行此命令,结果通常是不可预测的,因为控制台会尝试“提供帮助”并使用评估后的代码做一些奇怪的事情。

答案 2 :(得分:1)

它们是不同的,因为在{ a: y } =中,y是可以分配给的值容器(并被解析,因为您编写的表达式被解析为解构表达式)。 1是一个值,不能分配给它。因此,它不能构成有效的解构表达式。 { a: y = 1 } =并不代表{ a: ( y = 1 ) } =,而是y = 1; { a: y } =。同样,它是特殊的解构语义,可能与操作员通常的意义背道而驰。混合功能性和命令性语言范式的危险:)