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'自动分号插入'在这里没有按预期工作。但为什么呢?
我知道您可能会建议在任何地方使用;
以避免类似的情况,但问题不在于是否更好地使用;
。我想知道这里到底发生了什么?
答案 0 :(得分: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是一个字符串。正如Kamil指出的那样,a,b
是一个有效的Javascript表达式,该表达式的结果只是b
。
答案 1 :(得分: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
的值(在您的控制台中尝试)。没有b
undefined
值的属性,因此结果值也将为undefined
。
some
上没有方法undefined
,因此错误。
答案 2 :(得分: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
的返回值,您可能会遇到不同的错误。
答案 3 :(得分:1)
如果它是函数或流的最后一个语句,则可以避免';'
,但建议将';'
放在每个语句的末尾以避免此类错误。