`
hax
  • 浏览: 962416 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JavaScript的EOS(分号)问题

    博客分类:
  • JS
阅读更多
http://bbs.51js.com/viewthread.php?tid=83937&extra=page%3D1&page=1的讨论中,月影分析了JavaScript中EOS(End of Statement)存在的歧义问题。下面是我的回应。


是否要写“;”呢?

我经过几次反复。最开始是随便,想写就写。

后来都不写。

后来有段时间都写。

现在又都不写。


基本上现在的结果是我最后定型的习惯了。


原因:

1. 程序如果不追求太紧凑(例如要把多个语句写到一行里),分号确实是可以不用的。而且强制自己不用分号,其实是强制自己不要使用紧凑风格。

2. c-style的分号本来就是多余的。为什么这么说?因为明确的EOS只是给编译器的提示而已。而如果漏了分号,编译器会报错。既然它都报错了,显然它知道这里应该有EOS。既然它知道,那么干嘛还要我写?
某人说:【No expert programmers *hate* the situation in which the compiler throws out the program because of a missing semicolon. They ask the very reasonable question "if the compiler knows there should be a semicolon there why the **** doesn't it put it in?"】

所以明确的EOS只是给编译器的hint而已。这在几十年前是一个平衡编译器和用户成本的设计。但是放到现在,就未必了。JS以及许多语言的可选分号或可选EOS,其实就是一种回归。

3. 但是JS的严重问题是,它要兼顾(主要是兼顾从java那里继承下来的c-style的跨行语句习惯)。所以分号自动插入算法导致的实际结果是:EOS可能是分号,也可能是换行。麻烦的是,换行不一定是EOS。换行是否是EOS要看这一行和下一行结合起来。如果加上点括号啊,注释之类的,那到底EOS在哪里就头大了。

4. 所以问题仍然和最初类似,现行的JS的EOS规则,是为编译器(JS解释器)设计的(尽管初衷是为人的方便),而不是为“人”设计的。

5. 一个可供比较的例子是Groovy。它也是允许不写分号的。但是它的规则更好。基本不太会出现很难判断一个换行是否是EOS的例子。参见我的老文章:Groovy在EOS问题上的痛苦权衡

6. 本身js的规则也不能说太差,但是最让人反感的,是对括号的处理。也就是月影所举的一系列例子。假如不是因为对于括号处理的愚蠢设计,js的分号处理完全是可以接受的。

7. 所以如果像我一样,完全不写分号,就必须做到不在语句开始使用“(” 、“[”和其他歧义符号(如“+/-”)。这种情况本来也是比较少的。如对于(function...)的惯例法,可用void function或者new function来替代。

8. 其实出现歧义的情形,后续语句都是一个被丢弃结果的表达式(有例外的情形吗?),所以基本上可以在语句开始加上void运算符来明确,并且消除歧义。当然,更简单的方法是在引起歧义的语句之前(而不是之后)加上“;”。


总之,现在的状况是js的设计失误,如果没有工具支持(比如预处理器来补上“;”),那么从最佳实践的角度出发,就两种选择:

1. 月影的做法

每个语句之后写“;”

优点:作为规范,描述起来比较简单
缺点:老是要写烦人的“;”
陷阱:要记得,function表达式后面也要写“;”
另外,应该尽量避免写出有歧义的跨行语句,因为很难判断是有意为之,还是忘记写“;”。

2. 偶的做法

采用更严格的跨行策略,即只允许在当前行处于未完成状态时跨行(就像你在jsshell中输入代码一样)。
对于可能引起歧义的语句(行首为(、[、+/-等),在句首加上 void 或 “;”。

优点:省略了很多无聊的“;”
养成更良好的跨行代码习惯(适用于所有c-style的语言)
更容易应用工具(比如预处理器可以扫描出所有有问题的行,而对于传统的行尾加分号,工具只能warning,因为无法判断到底是有意跨行,还是忘记写“;”)
缺点:要判断歧义语句,另外在语句首加上void或“;”有点难看
陷阱:暂时没有发现
分享到:
评论
9 楼 luolonghao 2010-02-21  
我的做法是变量形式的加;,传统if、for、while、function都不加;。
var func = function() {
}; //加
var obj = {}; //加 
obj.abc = function() {
}; //加
function func() {
} //不加
var obj = {
}; //加
if () {
} //不加
for () {
}  //不加
8 楼 jindw 2010-02-21  
鹤惊昆仑 写道
YUI Compressor有问题。今天遇到一个诡异问题。1个js文件尾部有如下代码:var func = function(){//...}没有以分号结尾。另外一个js文件代码是这样的:(function(){})(arg); 这2个文件组合压缩成单行后就会自动执行func,就会触发不可预料的问题(如dom未加载时访问了dom)。所以还是严格点好,所有表达式结尾都加分号。这个问题太巧合了!

hax 写道
你可以用jindw的JSA。参考:http://www.iteye.com/topic/406387



合并压缩的问题。JSA对合并压缩至支持JSI工程导出处理。
对普通js压缩没有提供多文件支持,你得自己合并后压缩。安全起见,你可以文件之间用"\n;"分割 。JSA会自动删掉多余的";"号的
7 楼 hax 2009-12-24  
上面这个问题是存在的。所以这也是javascript语法的一个设计缺陷。

我个人建议,不是结尾都加分号(这个也不能确保别人都这样做)。而是在(...)这类括号开头的代码前主动加分号,这样你的正确性不依赖于别人。

详细的分析见:http://hax.iteye.com/blog/382186
6 楼 鹤惊昆仑 2009-12-24  
YUI Compressor有问题。今天遇到一个诡异问题。1个js文件尾部有如下代码:var func = function(){//...}没有以分号结尾。另外一个js文件代码是这样的:(function(){})(arg); 这2个文件组合压缩成单行后就会自动执行func,就会触发不可预料的问题(如dom未加载时访问了dom)。所以还是严格点好,所有表达式结尾都加分号。这个问题太巧合了!
5 楼 hax 2009-12-09  
你可以用jindw的JSA。参考:http://www.iteye.com/topic/406387
4 楼 aeoluszzf 2009-12-08  
YUI Compressor对省略分号的代码也不能正常压缩。。敢问hax用啥压缩工具啊?
3 楼 hax 2009-09-24  
那是minify工具没有做好。
2 楼 cjj 2009-09-24  
每行写;结尾 有点累 虽然现在养成的习惯 每行都写 不过可以少写几个 按逻辑块划分 一个逻辑块完成了 加个; 表示一个逻辑完成了 比如 if...else... for.... function 等
1 楼 jinweijie 2009-09-24  
不用分号的话,在minify以后可能会出错吧。

相关推荐

    浅谈javascript的分号的使用

    javascript大括号后面应使用分号吗?JS中function 的开头有加感叹号、分号是什么意思呢? Js多个文件集成成一个文件后,压缩代码时避免发生语法错误,可以如下处理 一、js 前加分号 例如:;(function($){…此处...

    分号带来的错误

    在本文中,我们将深入探讨“分号带来的错误”这一主题,特别是在计算1到100以内奇数之和的程序中可能出现的问题。 首先,让我们分析问题的背景。在计算1到100以内所有奇数的和时,我们通常会用到循环结构,如for或...

    JavaScript标准参考教程

    最后,编程风格章节强调了JavaScript编程中的风格问题,包括语法标记的风格和语句的编写方式。这包括了大括号的位置、圆括号的使用、缩进、行尾分号以及代码块的组织等。好的编程风格能够使代码更易读、易维护。 总...

    第15周-第21章节-Python3.5-javascript必须加分号.avi

    第15周-第21章节-Python3.5-javascript必须加分号.avi

    关于JavaScript语句后面的分号问题

    JavaScript自动加分号规则,有3条 当有换行符(包括含有换行符的多行注释),并且下一个token没法跟前面的语法匹配时,会自动补分号。 当有}时,如果缺少分号,会补分号 当程序源代码结束时,如果缺少分号,会补...

    Effective JavaScript 编写高质量JavaScript代码的68个有效方法1

    《Effective JavaScript:编写高质量JavaScript代码的68个有效方法》是David Herman撰写的一本JavaScript编程指南,该书基于作者在Ecma的JavaScript标准化委员会的工作经验,深入探讨了JavaScript的内部工作机制、...

    JavaScript入门篇,JavaScript基础知识

    JavaScript语句是向浏览器发出的命令,每个语句以分号`;`结尾。例如,`alert("hello!");`就是一个简单的语句,它会弹出一个对话框显示“hello!”。在编写代码时,良好的编程习惯是使用分号,尽管它们在某些情况下...

    走进javascript——不起眼的基础,值和分号

    此外,一些JavaScript插件开发者在代码的第一行添加一个分号,目的是为了防止可能由于插件使用者的代码风格不同导致的问题。如果后续的脚本中省略了分号,且与之前的代码有语义上的联系,可能会引起解析错误或者意外...

    EOS6 RichWeb开发指南 ,介绍EOS6的相关文档,欢迎下载!

    RichWeb是EOS6提出的概念,旨在提供一种更接近传统Web开发体验的框架,让开发者可以利用熟悉的前端技术如HTML、CSS和JavaScript构建去中心化的应用。RichWeb的核心在于将Web的富媒体体验与区块链的去中心化特性相...

    英文版javascript教程

    - 分号在JavaScript中是可选的,如果一行代码的末尾没有其他语句,JavaScript解释器会自动将其视为语句的结束。 以上内容是基于教程的部分内容提取的知识点,详细介绍了JavaScript语言的基础知识和基本语法结构。...

    深入理解JavaScript系列

    本书是一本全面、深入介绍JavaScript语言的学习指南。本书共分四个部分,第1部分帮助读者快速入手,掌握基本的JavaScript编程要点;第2部分介绍JavaScript的发展和技术背景;第3部分深入探索JavaScript,介绍了语法...

    javascript国际化问题,js国际化

    这是一个关于处理javascript的国际化问题的一篇技术文章。

    普元EOS实例

    `eos-web`可能是一个包含Web应用资源的目录,如HTML、CSS、JavaScript,这些资源可能与EOS Bank的服务接口或者用户界面相关。 `com.primeton.bank.service`是服务相关的Java源代码包,这里包含了银行服务的具体实现...

    Google_JavaScript_编码规范指南

    4. 分号的使用:在JavaScript中,推荐使用分号来明确语句的结束,避免因为自动分号插入机制(ASI)导致的问题。分号的使用有助于防止由于缺少分隔符而导致的语法错误或逻辑错误。 5. 嵌套函数:嵌套函数是在另一个...

    JavaScript中的分号插入机制详细介绍

    此外,省略分号可能导致脚本连接问题。如果两个JavaScript文件被合并在一起,如: ```javascript // file1.js (function () { //…… })(); // file2.js (function () { //…… })(); ``` 将被视为: ```...

    JavaScript基本语法.pdf

    如果省略分号,JavaScript会尝试自动插入,但这可能导致代码出错,尤其是在压缩或自动格式化的代码中。良好的编码习惯是每行语句末尾都添加分号。 4. **程序注释** 注释在JavaScript中非常重要,因为它提高了代码...

    JavaScript文档

    本资源包包含了多个关于JavaScript的重要参考资料,包括“JavaScript权威指南(英文版).chm”、“javascript5.5.chm”、“css2gb.chm”以及“JavaScript对象与数组参考大全 .chm”。 首先,我们来看“JavaScript权威...

    javaScript经典实例

    9. **异步编程**:Promise、async/await等机制解决了JavaScript中的回调地狱问题,让异步代码更易于理解和维护。 10. **模块化**:CommonJS、AMD、ES6模块等方案使得JavaScript代码可组织为模块,提高代码复用性...

Global site tag (gtag.js) - Google Analytics