在 javascript 中传播语法后使用分号会中断执行并出现错误“Unexpected token =”

Posted

技术标签:

【中文标题】在 javascript 中传播语法后使用分号会中断执行并出现错误“Unexpected token =”【英文标题】:Having semicolon after spread syntax jn javascript breaks execution with error "Unexpected token =" 【发布时间】:2018-12-02 20:09:41 【问题描述】:

谁能解释一下原因

const getabc = ()=> (a:'aa',b:'bb',c:123);
let a, b, c;
 a, b, c  = ...getabc()

这行得通

const getabc = ()=> (a:'aa',b:'bb',c:123);
let a, b, c;
 a, b, c  = ...getabc();

这不是(注意最后的分号)

【问题讨论】:

为什么要传播?这是多余的。 @NinaScholz ***.com/help/mcve 这是一个最小的例子。 第一个在 Firefox 上不起作用,得到SyntaxError: expected expression, got '=' @RaymondChen,我和 mcve 有什么关系?该对象是用另一个对象生成的。生成的对象用于解构并且不再使用。财产被转移。所以是多余的。 两者都在 Chrome 中产生错误。 【参考方案1】:

这与展开语法或分号无关。

前面没有varconstlet 之类的对象解构赋值必须使用括号(或以其他方式作为包含它的更大语句中的表达式出现),否则 JS 将将左大括号解析为块的开头:

const getabc = ()=>(a:'aa',b:'bb',c:123);
let a, b, c;
( a, b, c  = ...getabc());

同时,这里使用展开语法没有意义,所以你可以删除它:

const getabc = ()=>(a:'aa',b:'bb',c:123);
let a, b, c;
( a, b, c  = getabc());

【讨论】:

【参考方案2】:

根据MDN documentation,您缺少括号:

一个变量可以通过解构来赋值 它的声明。

var a, b;

(a, b = a: 1, b: 2);

const getabc = ()=>(a:'aa',b:'bb',c:123);
let a, b, c;
( a, b, c  = ...getabc());
console.log(a,b,c);

我的猜测是第一个是 Chrome 实现中的错误,因为 Firefox 会抛出错误。

火狐

【讨论】:

Chrome 在 OP 给出的示例中也给出了相同的错误。 @Ivar 不,它们是不同的。我已经附加了来自 Chrome 和 FF 的控制台输出。 这很奇怪。它确实从命令行以这种方式工作。如果我在 OP 的帖子中运行代码 sn-ps,我确实会收到两次相同的错误。 就像我说的,可能是实现中的一个错误【参考方案3】:

这是 Chrome 的 hidden way 和 helping developers 的人工制品。即它会自动将某些表达式包装在括号中(或评估它们好像包装,没有区别)所以

a = a: true

实际上被评估为好像

(a = a: true)

第一个是不是一个有效的语句,但是,因为 被评估为a code block - 与if (cond) for() function() 相同的构造,而不是对象字面量语法或对象解构语法。

应该注意,这是代码的正确解释——它应该抛出一个语法错误,因为它是无效的:

a = a: true

添加括号可以避免开头的被解释为代码块:

(a = a: true)

console.log(a);

Chrome 的控制台会将其隐藏起来。作为比较,Firefox 也会产生相同的结果 - 一个错误。

但是,当您添加分号时,表达式不再对括号有效:(a = a: true;) 没有意义,因此 Chrome 会完全按照所写的方式对其进行评估,这也是两种情况下的正确解释:

a = a: true;

此行为存在于 V8 相关的 REPL 环境中。例如,在 Opera 或 Node.JS REPL 中也可以观察到相同的情况。在评估正常上下文中的代码而不是使用 REPL 常规解析规则时,表达式 a = a: true 会引发错误。 See here on repl.it 或者换个地方测试

创建一个包含a = a: true 的文件并通过节点执行它(repl.it 中的中间面板) 在节点 REPL 中输入相同的代码(repl.it 中的右侧面板)

如果您想知道“为什么不直接忽略一般情况下的代码块”,这可能会导致错误或至少会导致语法混乱。例如,这是使用代码块的有效代码

let a = 1;


  let a = 2;
  console.log("inside block", a);


console.log("outside block", a);

视为代码块以外的任何内容将是一个问题。

【讨论】:

完美回应,有道理。感谢您的链接和解释。

以上是关于在 javascript 中传播语法后使用分号会中断执行并出现错误“Unexpected token =”的主要内容,如果未能解决你的问题,请参考以下文章

text javascript中语法上不强制需要分号的情形

JavaScript的语法规则

JavaScript 传播语法与 jQuery $.extend - ByRef 和 ByVal

JavaScript - 如何合并/附加到对象/数组 - ReactJS - 传播语法

为啥我应该在javascript中的每个函数后使用分号?

js01-javascript语法标准和数据类型