[]之前没有分号在JavaScript中导致错误

问题描述 投票:9回答:4

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'自动分号插入'在这里没有按预期工作。但为什么?

我知道你可能会建议在任何地方使用;来避免这样的事情,但问题不在于是否更好地使用;。我想知道这里究竟发生了什么?

javascript arrays syntax automatic-semicolon-insertion
4个回答
13
投票

当我担心分号插入时,我会想到在它们之间没有任何空格的情况下,所讨论的行会是什么样子。在你的情况下,那将是:

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是一个字符串。正如卡米尔指出的那样,a,b是一个有效的Javascript表达式,该表达式的结果只是b


8
投票

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

如果在新行导致解析错误之后没有结束语句,Javascript只会考虑使用新行来标记语句的结尾。有关确切的规则,请参阅What are the rules for JavaScript's automatic semicolon insertion (ASI)?EcmaScript 5 spec。 (感谢Rob W和众人瞩目)

会发生什么是以下情况:

代码被解释为

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

即所有作为一个声明。

现在解析声明:

some被称为console.log([a,b].length)[a,b]的价值

console.log([a,b].length)[a,b]的值是通过获取console.log([a,b].length)undefined)的返回值然后尝试访问具有a,b值的属性来计算的。 a,b评估b的值(在你的控制台中尝试)。没有bundefined值的属性,因此得到的值也将是undefined

some上没有方法undefined,因此错误。


6
投票

JavaScript不会将每个换行符视为分号。它通常仅在没有分号的情况下解析代码时将换行符视为分号。基本上,如果下一个非空格字符不能被解释为当前语句的延续,则JavaScript将换行符视为分号。 JavaScript - The Definitive Guide: 6th Ed. section 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的返回值,您可能会遇到不同的错误。


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.