新收获——神奇的语句结束界定
在JavaScript,换行分号是一个非常例外的存在,不同于Java强制要求分号结尾语句,也不同于python强制不使用分号,它既可以使用也可以不使用,在我编码的大多数项目中,我都遵循了语句结束以分号结尾,因此我一直未发现如果不以分号结束,JavaScript引擎的语句结束解析是如此神奇:
例子:
const a = 1
[1,2].indexOf(1) //报错
这段代码中,分开来阅读,第一行,定义一个变量a,并把1赋值给a,第二行则是获取数组[1,2]中1所在的索引,看似没有什么问题,但实际运行后会发现产生了报错Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf') ,意为indexOf未定义,到此其实不难发现,之所以indexOf未定义是因为在第一行代码中虽然输入了换行符,但这并不意味着JavaScript解释器以此换行符为语句结束,也就是上述代码会解析器理解为:
const a = 1[1,2].indexOf(1) //报错
由此可以发现,JavaScript解释器对于语句结束的解析方法,并不是我们阅读习惯上的以换行为界限,而是只在下一个非空格字符无法被解释为当前语句的一部分时才把换行符当作分号。对应例子来说,“[”号被JavaScript理解为第一行代码的一部分。通俗来说就是如果下一句代码的第一个字符和当前代码毫无关系时,换行符才会被正确解析为分号,否则会被视为同一行代码。
通常,如果语句以(、[、/、+或-开头,就有可能被解释为之前语句的一部分。实践中,以/、+和·开头的语句极少,但以(和[开头的语句则并不鲜见,至少在某种JavaScript 编程风格下经常会看到
一些特殊情况
上面说到换行符可能不会被正确识别为分号,但是在以下三种情况中,我们可能会误以为前后两句代码会被JavaScript解释器解析为同一句,但实际上并不是:
1.return、throw、yield、break和continue语句
在使用这些语句同时不以分号作为结束规范时,这些短语组成了一条语句,但是有时候我们会在其后加入一些表达式,比如
return
true;
我们可能的意图:
return true;
但实际上,JavaScript以为的:
return; true;
2.++和-- 操作符
这些操作符既可以放在表达式前面,也可以放在表达式后面。如果想把这两个操作符作为后置操作符,那它们必须与自己操作的表达式位于同一行
3.箭头函数
使用简洁的“箭头”语法定义的函数箭头 => 必须跟参数列表在同一行。
总结:
在不使用分号为语句结束符时,应该注意换行符大多数情况下会被正常解析为结束符,但是以(、[、/、+或-开头的语句会因被视为上一行代码未结束部分而不会被正常解析,理解了这一点之后,还要注意有三种特殊情况,换行符会被正常解析为结束符
评论区