`
hax
  • 浏览: 968503 次
  • 性别: 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中分号的一些细节.docx

    分号在JavaScript中作为语句的终止符,它的主要功能是作为语句的断言(End Of Statement, EOS),用来结束一个程序语句。尽管在很多C风格的语言中,分号的存在主要是为了简化编译器的设计,但现代编译器已能够高效地...

    EOS入门必备.doc

    本教程作为EOS程序员的培训教程,旨在帮助初学者理解EOS的运行机制、原理,以及在开发过程中需要注意的关键问题。 **一、CSS** 1. **CSS介绍**:CSS(Cascading Style Sheets)是用于控制网页元素呈现样式的语言。...

    浅析Javascript的自动分号插入(ASI)机制

    相信从事过C#和Java的大家都知道分号是用作断句(EOS,end of statement)的,而且必须加分号,否则编译就不通过了。但JavaScript由于存在ASI机制,因此允许我们省略分号。ASI机制不是说在解析过程中解析器自动把...

    EOS入门必备,EOS入门必备

    属性值通常由冒号分隔,每条声明以分号结束。例如: ```css h1 { color: #333; /* 颜色 */ font-size: 24px; /* 字体大小 */ } ``` 5. **用法示例** CSS可以用于控制布局、定位、背景、边框等多种视觉效果。...

    JEDEC SPEC 最新版 合集 DDR2/DDR3/DDR4/DDR5/LPDDR2/LPDDR3/LPDDR4(X)/LPDDR5(X)

    JESD79-2F DDR2 JESD79-3F DDR3 JESD79-4D DDR4 JESD79-5C DDR5 JESD209-2F LPDDR2 JESD209-3C LPDDR3 JESD209-4E LPDDR4 JESD209-4-1A LPDDR4X JESD209-5C LPDDR5(X)

    COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,comsol二维光子晶体角态 单胞能带,超胞能

    COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,COMSOL二维光子晶体角态研究:单胞与超胞能带计算及边界态与角态特性分析,comsol二维光子晶体角态。 单胞能带,超胞能带,边界态以及角态计算。 ,comsol;二维光子晶体;角态;单胞能带;超胞能带;边界态计算,基于Comsol的二维光子晶体角态及能带边界计算研究

    六自由度机械臂抓取动作仿真与代码解析:抓取动画、关节参数变化及轨迹图解详解,六自由度机械臂抓取动作仿真指南:掌握两套代码实现动画与轨迹图模拟学习攻略,六自由度机械臂抓取动作仿真-8 两套关于抓取动作的

    六自由度机械臂抓取动作仿真与代码解析:抓取动画、关节参数变化及轨迹图解详解,六自由度机械臂抓取动作仿真指南:掌握两套代码实现动画与轨迹图模拟学习攻略,六自由度机械臂抓取动作仿真-8 两套关于抓取动作的代码,包括抓取动画、关节角、角速度、角加速度的变化仿真、以及抓取轨迹图 简单易懂好上手~ ,六自由度机械臂;抓取动作仿真;抓取动画;关节角变化;角速度角加速度;抓取轨迹图;两套代码;简单易懂好上手,六自由度机械臂抓取动作仿真演示:代码与轨迹图解

    ITC网络广播工具软件

    ITC网络广播工具软件

    Multisim四位密码锁电路仿真设计:设定、开锁与声光报警功能演示资料包,Multisim四位密码锁电路仿真设计:设定、输入、开锁与报警功能详解,附源文件、原理说明书与演示视频,multisim四位

    Multisim四位密码锁电路仿真设计:设定、开锁与声光报警功能演示资料包,Multisim四位密码锁电路仿真设计:设定、输入、开锁与报警功能详解,附源文件、原理说明书与演示视频,multisim四位密码锁电路仿真设计 功能: 1.通过拨码开关1进行初始密码设定。 2.通过拨码开关2输入密码,实现开锁判断。 3.如果密码正确,LED绿灯亮,表示开锁。 4.如果密码不正确,LED红灯亮,蜂鸣器鸣叫,声光报警。 资料包含:仿真源文件+原理说明书+演示视频 ,四位密码锁电路、Multisim仿真设计、初始密码设定;拨码开关输入;开锁判断;LED灯显示;声光报警;仿真源文件;原理说明书;演示视频,Multisim四位密码锁电路仿真设计:初始密码设置与智能解锁功能的声光报警展示

    上班摸鱼打卡模拟器微信小程序源码.zip

    俗话说,摸鱼摸的好,上班没烦恼,毕竟谁能拒绝带薪拉屎呢(手动狗头) 这是一个云开发职场打工人专属上班摸鱼划水微信小程序源码,没有后台 直接导入微信开发者工具即可运行,UI简约大气漂亮,只需登录微信公众平台配置完合法域名即可轻松上线。 用户进入摸鱼小程序,可以自由设置薪资,上班时间、下班时间、发薪日、 月工作天数以提醒自己摸鱼,全民打酱油,让自己成为摸鱼冠军,《商鞅摸鱼哲学》 摸鱼不是自我放纵,而是个人实力的积蓄,我们的小目标是晚睡晚起 小程序中的今日待办会提醒用户带薪拉屎和闲逛,下方展示的是距离休息日的天数,距离下一次发工资的天数和节日的天数。

    【毕业设计】基于Java的开发的一个集合校园二手交易、拼车、失物招领等功能的app_pgj.zip

    【毕业设计】基于Java的开发的一个集合校园二手交易、拼车、失物招领等功能的app_pgj

    PICkit3离线烧录流程

    个人记录:PICkit3离线烧录流程 使用软件:MPLAB X IDE v5.30 记录时间:20250215

    基于Matlab代码的电力系统状态估计与实验仿真研究:扩展卡尔曼滤波和无迹卡尔曼滤波在电力系统动态状态估计中的应用及效果分析,Matlab仿真实验研究:基于扩展卡尔曼滤波器与无迹卡尔曼滤波器对电力系统

    基于Matlab代码的电力系统状态估计与实验仿真研究:扩展卡尔曼滤波和无迹卡尔曼滤波在电力系统动态状态估计中的应用及效果分析,Matlab仿真实验研究:基于扩展卡尔曼滤波器与无迹卡尔曼滤波器对电力系统状态估计的影响及验证,状态估计 电力系统状态估计 Matlab代码 实验仿真研究 电力系统由于测量值和传输误差,还有测量噪声的影响,会对状态估计产生影响。 因此,需要对嘈杂的测量进行滤波,以获得准确的电力系统运行动态。 本文使用扩展卡尔曼滤波器(EKF)和无迹卡尔曼滤波器(UKF)来估计电力系统的动态状态。 扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF 利用扩展的无迹卡尔曼滤波器估计了动力系统的动态状态。 对WECC 3机9总线系统和新英格兰10机39总线系统进行了案例研究。 结果表明EKF和UKF都能准确地估计电力系统的动态状态。 ,核心关键词:状态估计; 电力系统状态估计; Matlab代码; 实验仿真; 测量值误差; 测量噪声; 扩展卡尔曼滤波器(EKF); 无迹卡尔曼滤波器(UKF); 动力系统; 动态状态估计; WECC 3机9总线系统; 新英格兰10机39总线系统。,Matlab

    springboot在线考试--.zip

    springboot在线考试--

    台达DVP EH3与MS300 PLC&变频器通讯程序的全面解决方案,台达DVP EH3与MS300通讯程序:稳定可靠的频率控制与启停管理系统,台达DVP EH3与台达MS300通讯程序(TDEH-9

    台达DVP EH3与MS300 PLC&变频器通讯程序的全面解决方案,台达DVP EH3与MS300通讯程序:稳定可靠的频率控制与启停管理系统,台达DVP EH3与台达MS300通讯程序(TDEH-9) 可直接用于实际的程序,程序带注释,并附送触摸屏程序,有接线方式和设置,通讯地址说明等。 程序采用轮询,可靠稳定 器件:台达DVP EH3系列PLC,台达MS300系列变频器,昆仑通态7022Ni 功能:实现频率设定,启停控制,实际频率读取,加减速时间设定。 资料:带注释程序,触摸屏程序,接线和设置说明,后续有技术咨询。 ,核心关键词:台达DVP EH3; 台达MS300; 通讯程序(TDEH-9); 轮询; 稳定; 频率设定; 启停控制; 实际频率读取; 加减速时间设定; 触摸屏程序; 接线方式; 设置说明; 技术咨询。,台达PLC与变频器通讯程序(带注释、触摸屏控制)

    【python毕设】p100基于Pytorch+springboot+vue的声纹识别系统.zip

    项目资源包含:可运行源码+sql文件 适用人群:学习不同技术领域的小白或进阶学习者;可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。项目具有较高的学习借鉴价值,也可拿来修改、二次开发。 个人账户管理:支持用户注册、登录与个人信息编辑;提供密码找回及账号安全保护措施。 声纹采集:利用麦克风设备录制用户的声纹样本;支持多种录音格式和质量调整,确保采集到清晰、准确的声纹数据。 声纹模板库管理:建立和维护一个安全的声纹模板库;支持声纹模板的添加、删除、更新和查询操作。 声纹比对与识别:运用深度学习算法对输入的声纹数据进行特征提取和匹配;实现快速、准确的声纹身份验证。 多场景应用支持:适用于多种场景,如门禁系统、移动支付、远程登录等;可根据实际需求定制开发相应的应用场景。 实时监控与报警:实时监控系统运行状态,包括声纹识别成功率、处理速度等指标;当出现异常情况时,及时发出报警信息。 数据分析与报告生成:收集并分析声纹识别过程中的数据,如识别准确率、处理时间等;根据用户需求输出包含详细图表说明的专业级文档供下载打印保存。 社区互动交流:设立论坛版块鼓励用户分享心得体会讨论热点话题;定期邀请行业专家举办线上讲座传授实用技巧知识。 音乐筛选与推荐:集成音乐平台API,根据用户的浏览习惯和情绪状态推荐背景音乐,增强用户体验。 数据可视化:提供交互式的数据可视化面板,使非技术用户也能轻松理解复杂的数据集,从而做出更明智的决策。

    三相与多相开绕组永磁同步电机仿真模型的先进控制策略探讨与实现,三相与多相开绕组永磁同步电机的Simulink仿真模型与先进控制策略研究,开绕组电机,开绕组永磁同步电机仿真模型、simulink仿真 共

    三相与多相开绕组永磁同步电机仿真模型的先进控制策略探讨与实现,三相与多相开绕组永磁同步电机的Simulink仿真模型与先进控制策略研究,开绕组电机,开绕组永磁同步电机仿真模型、simulink仿真 共直流母线、独立直流母线,两相容错,三相容错控制,零序电流抑制,控制策略很多 三相开绕组永磁同步电机,六相开绕组永磁同步电机 五相开绕组永磁同步电机,五相开绕组电机 ,开绕组电机; 永磁同步电机仿真模型; simulink仿真; 共直流母线; 独立直流母线; 两相容错; 三相容错控制; 零序电流抑制; 控制策略; 六相开绕组永磁同步电机; 五相开绕组永磁同步电机,开绕组电机仿真研究:共直流母线与独立直流母线的容错控制策略

    【毕业设计】基于Java的开发的网上汽车租赁管理系统_pgj.zip

    【毕业设计】基于Java的开发的网上汽车租赁管理系统_pgj

    python打开csv文件

    csv 模块是 Python 的标准库,无需额外安装。 运行结果如下图: ['姓名', '年龄', '城市'] ['张三', '25', '北京'] ['李四', '30', '上海'] ['王五', '22', '广州']

    【毕业设计】基于Java+Springboot+Vue的宠物领养系统_pgj.zip

    【毕业设计】基于Java+Springboot+Vue的宠物领养系统_pgj

Global site tag (gtag.js) - Google Analytics