auto semicolon insertion 自动分号补齐的坑

今天发现js自动分号补齐的坑,来看如下两段代码:

function Hello(){
    return
    {
        name: ’JavaScript’
    };
}

alert(Hello());


//输出undefined

  

function Hello(){
    return{
        name: ’JavaScript’
    };
}

alert(Hello());


//输出 [object Object]

  略看代码,差不多,但是输出却不一样。仔细看看第一段代码return后面多了个换行。我们平时写后端代码也经常有会这样换行后花括号左对齐的写法。但是在js这里这样写却有不同的输出。这种机制叫分号自动补齐机制( auto semicolon insertion,简称ASI )。

  知乎上有大神关于这个机制的解释:

  链接: https://www.zhihu.com/question/21076930/answer/17135846

在ASI的机制中有一类语句叫做restricted productions(不知道中文叫啥)。简单来说,就是组成这类语句的两个token当中不允许出现换行符 \n。如果在第一个token后面遇到了换行符,则判断语句结束,插入分号。restricted productions包括:

  • return xxx (xxx是要返回的对象)
  • throw xxx(xxx是要抛出的错误对象)
  • break / continue xxx(xxx是循环的标签)
  • 作为后缀的 ++ / --

其中前几个关键词还是挺容易记的,最后一条的原因是需要区分以下情况:
a
++
b

因为++/--既可以作为前缀又可以作为后缀,在这样的情况下作为后缀解析会遇上换行符,所以只能作为b的前缀,自动插入分号后变成:
a; ++b;

回到原题,Douglas Crockford认为 { 应该写在行尾,是为了避免换行符导致return直接返回undefined。

篇外:关于分号 ------------------------------------------------------------------------------------------------

很多人觉得ASI坑太多了所以提倡永远手动加分号,这样就不用费心去研究ASI的规则了。但事实上,即使永远手动加分号,你依然会被restricted productions这条规则坑,因为它是在你不想要分号的地方给你插入分号。所以不管你喜不喜欢分号,都最好花点时间好好了解一下ASI的规则。而一旦你知道了ASI所有的坑,不写分号其实是很简单的。

ASI真正需要注意的坑只有两个,restricted productions是其一,另一个就是当下一行开头是 ( [ / 这三个字符之一的时候:
a = b
(function () { ... }())
会被解析成
a = b(function () {...}());

换言之,( ) 会被看做是在调用函数b。同理,[ ] 会被看做是在获取b的属性,而被斜杠坑的情况则要求更苛刻一些:
a = b
/Error/i.test(str) && doSomething()
第二行的写法本身比较少见,但也不是不可能。结果会被解析成:
a = b / Error / i.test(str) && doSomething();

斜杠被解析成了除号!

要躲开这个坑,其实真的挺简单,只要尽量别用这三个字符作为一行开头就行了。事实上遇到比较多的也只有括号开头。真的避不开的话,可以在行头手动加个分号:
a = b
;(function () { ... }())

额外的一点是在for循环声明里面的分号是永远不能省的,ASI不会在for循环声明中插分号,但一般正常人不会把for的声明分三行写吧...

每次我看到 “javascript分号坑很多,所以应该永远加分号” 这样的说法总是有些不屑的,因为永远加分号并不是避免错误的办法,搞懂ASI是怎么回事才是。只要理解了这里说的两个坑,javascript里99%的分号都是不必要的。

  

转载于:https://www.cnblogs.com/zhangcybb/p/7018576.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值