[] 前没有分号会导致 JavaScript 错误

IT技术 javascript arrays syntax automatic-semicolon-insertion
2021-02-06 17:58:21

var a = [1, 2, 3, 4];
var b = [10, 20, 30, 40];
console.log([a, b].length)
[a, b].some(function(x) {
  x.push(x.shift())
});

今天当这段代码导致我非常惊讶

[a,b].some(function(x){ x.push(x.shift()) });
      ^
TypeError: Cannot call method 'some' of undefined

显然,JavaScript 的“自动分号插入”在这里没有按预期工作。但为什么?

我知道您可能会建议在;任何地方使用以避免类似的情况,但问题不在于使用是否更好;我很想知道这里到底发生了什么?

4个回答

当我担心分号插入时,我会考虑相关行之间没有任何空格的情况。在你的情况下,那将是:

console.log([a,b].length)[a,b].some(function(x){ etc });

在这里,您告诉 Javascript 引擎以console.log的长度进行调用[a,b],然后查看[a,b]该调用结果的索引

console.log返回一个字符串,因此您的代码将尝试查找b该字符串的未定义属性,并且调用undefined.some()失败。

有趣的是,str[a,b]将解析为str[b]假设 str 是一个字符串。正如 Kamil 指出的,a,b是一个有效的 Javascript 表达式,该表达式的结果只是b.

我不认为 console.log 返回一个字符串。
2021-03-28 17:58:21
arr[a, b]不是多维数组访问。它与arr[b]因为a, b是在最后一个逗号之后具有内部表达式值的有效表达式相同
2021-04-11 17:58:21

一般来说,可以说在新行上定义数组时隐式分号很容易失败,因为在新行上定义的数组被解释为对上一行表达式值的属性访问。

如果在这个新行之后结束语句会导致解析错误,Javascript 只会考虑新行来标记语句的结束。请参阅JavaScript 的自动分号插入 (ASI) 的规则是什么?EcmaScript 5 规范的确切规则。(感谢 Rob W 和聚光灯下)

发生的情况如下:

代码被解释为

console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });

即全部作为一个声明。

现在解析语句:

some 被称为value console.log([a,b].length)[a,b]

的值console.log([a,b].length)[a,b]是通过获取console.log([a,b].length)( undefined)的返回值然后尝试访问具有 值的名称的属性来计算的a,ba,b评估为b(在您的控制台中尝试)的值。没有值为 ofb属性undefined,因此结果值undefined也是如此。

有没有一种方法someundefined,因此错误。

JavaScript 不会将每个换行符都视为分号。仅当它无法在没有分号的情况下解析代码时,它通常才会将换行符视为分号。基本上,如果下一个非空格字符不能被解释为当前语句的延续,JavaScript 会将换行符视为分号。JavaScript - 权威指南:第 6 版。第 2.4 节

因此,在您的情况下,它将该行解释为类似

console.log([a,b].length)[a,b].some(function(x){ x.push(x.shift()) });

这就是错误的原因。JavaScript 试图对console.log([a,b].length). 根据 JavaScript 引擎和 的返回值console.log,您可能会收到不同的错误。

如果是函数或流程的最后一条语句,则可以避免,';'但建议放在';'每条语句的末尾以避免此类错误。