团队开发中编写高可维护性的JS代码首先要统一编程风格,不管谁写的代码看起来都像出自一个人之手,这样大家就能更好地理解和维护对方的代码
编程风格是编码规范的一种,编码规范还包括最佳实践、文件和目录的规划以及注释等方面
编码规范重要的几个原因:
- 软件生命周期中80%的成本消耗在维护上(深有体会T_T)
- 几乎所有的软件维护者都不是它的最初作者
- 编码规范提高了软件的可读性,让工程师能快速且充分地理解新的代码
- 若将源码作为产品发布,你需要确保它是可完整打包的,且像你创建的其他产品一样整洁
检查编程风格的工具:JSLint和JSHint,可找出代码中潜在的错误还能针对你的代码给出编程风格上的警告
本书作者在编程风格方面,会提及jQuery核心风格指南、Goolge的JavaScript风格指南、Dojo编程风格指南等指南
以下是作者个人的JavaScript编程风格
缩进层级
Tab缩进和空格缩进,二选一但不要混用
使用Tab缩进的一个缺点是用不同系统的相同编辑器打开文件时看到的缩进不一样,因为系统对制表符的解释不一致
使用空格缩进缺点是累...
推荐做法是使用4个空格作为一个缩进,编辑器配置敲Tab键时会插入几个空格,这样不但省力而且能保证在所有系统和编辑器里的代码呈现是一模一样的、
语句结尾
语句结尾不要省略分号
JS之所以能省略分号是因为有赖于分析器的自动分号插入(ASI)机制,ASI分号插入规则非常复杂难记,某些场景我们认为不需要插入分号而ASI认为需要插入时,就会产生错误,所以不要省略分号
行的长度
每行代码长度限定在80个字符
很久以前文本编辑器单行最多只能显示80个字符,所以书写习惯也保留了下来
(这个我没有好好遵守,因为现在屏幕大了,每行80个字符的话看起来整个版面很窄...先记下来吧可能以后会领悟其中深意)
换行
当单行太长时需要换行
在运算符后换行,下一行增加两个缩进
逗号(运算符)之后换行,否则ASI会在某些场景下在行结束位置插入分号就会报错,若总是将一个运算符置于结尾,ASI就不会自作主张插入分号
当给变量赋值时,下一行的位置应与等号对齐
空行
- 流程控制语句(如if和for)前要加空行
- 方法间加空行
- 方法中变量赋值和第一条语句间加空行
- 单行或多行注释前加空行
- 代码语义不相关时可加空行确保语义有关的代码展现在一起,而不相关的加入空行后能提高可读性
命名
命名使用小驼峰,如anotherVariable
变量名前缀应该是名词,函数名前缀应该是动词,如count、getName,一眼就可区分变量和函数
常量名全用大写字母,多个单词用下划线隔开,如MAX_COUNT
命名尽可能短并抓住要点,见名知意,避免使用如foo、tmp之类没有意义的名字,因为对于其他开发者来说,若没看过上下文,无法理解这些变量用处
有一些函数名常见前缀:can、has、is、get、set等
构造函数遵循大驼峰
字面量
字符串单引号或双引号,应该从头到尾只保持使用一种,嵌套使用时除外
多行字符串应使用+连接符
技术上讲这种写法是非法的JS语法,但的确能在代码中创建多行字符串,不推荐此种写法,因为其是种奇巧淫技而非语言特性
小数不要省略小数点前后的数字
不小心丢掉小数点还是刻意为之,为了避免歧义,不要省略小数点前后的数字
同时长久以来JS支持八进制数字写法是很多错误和歧义的根源,所以不要使用八进制字面量
null
以下场景应当使用null
- 当一个变量可能赋值为一个对象时,可赋值为null,将变量初始值赋为null表明了这个变量最终很可能赋值为对象
- 用来和一个已经初始化的变量比较,这个变量可以是也可不是一个对象
- 当函数的参数期望是对象时,用作参数传入
- 当函数的返回值期望是对象时,用作返回值传出
理解null最好的方式是将它当作对象的占位符(应该就是null和对象挂钩,之后无论结果是对象还是null,我们都知道操作的是对象)
不应使用null的场景
- 不要用null来检测是否传入了某个参数
- 不要用null来检测一个未初始化的变量
undefined
出现undefined的情况有两种,变量未声明,或声明了未初始化
避免使用undefined,变量初始化时赋值为null,而typeof null返回的是“object”,这样typeof返回“undefined”就只有一种情况,那就是变量未声明
对象和数组字面量
推荐使用字面量的方式创建对象和数组,而不是new的方式,这样会更高效
注释
注释前都应有一个空行,单行注释//后有个空格,代码尾部的单行注释距离代码结束位置至少有一个缩进,若超出单行字符限制,则将注释放置代码行上方
多行注释推荐使用Java风格
如下情况应该使用注释:
代码晦涩难懂
可能被误认为是错误的代码
必要但并不明显的针对特定浏览器的代码
对于对象、方法或属性,生成文档是有必要的(使用恰当的文档注释)
语句和表达式
所有的块语句都应使用花括号,特备是if
- if
- for
- while
- do...while...
- try..catch..finally
块语句间隔
在左括号之前和右括号之后添加一个空格
switch
- 每条case语句相对于switch关键字都缩进一个层级
- 从第二条case语句开始,每条case语句前后各有一个空行
关于case穿透,建议是只要有意为之并添加了注释,就可穿透
关于default,很多人认为无论什么时候都不应省略default,哪怕default什么也不做
作者倾向于在没有默认行为且写了注释的情况下是可以省略default的
循环
for语句的初始化部分不应当有变量声明
for-in循环可遍历数组,但不推荐,因为会造成潜在的错误,for-in是用来对实例对象和原型链中的键做遍历的,而不是用来遍历包含数字索引的数组
并且for-in遍历最好使用hasOwnProperty()方法来过滤实例属性,否则它不但遍历对象的实例属性还遍历从原型中继承来的属性
除非你想查找原型链,此时应当补充注释
变量、函数和运算符
建议总是将局部变量的定义做为函数内的第一条语句,并且使用“单var语句”
每个变量的初始化独占一行,对于那些没有初始值的变量,应放var语句尾部
函数声明
推荐总是先声明函数再去使用,因为预解析的存在,所以最好符合其行为
另外,函数声明不应出现在块语句中
这段代码在不同浏览器中的运行结果不尽相同,不管condition的计算结果如何,大多数浏览器都会自动使用第二个声明,而Firefox则根据condition的计算结果选用合适的函数声明。这种场景是ECMAScript的灰色地带,应当尽可能地避免,函数声明应当在条件语句的外部使用
自调用函数
为了增加阅读性,自调用函数应用括号包裹起来
此例子中,会让人误以为将一个匿名函数赋值给这个变量,除非读完整段代码看到最后一行的括号,否则不会知道是将函数赋值给变量还是将函数的执行结果赋值给变量
严格模式
严格模式最好不要用在全局,如果你将11个文件合并成一个文件时,当其中一个文件在全局中启用了严格模式,则所有代码都将以严格模式解析,很可能会报错
若不想写太多的“usestrict”,可使用自调用函数
相等
推荐毫无例外都是使用=和!来代替==和!=来避免弱类型转换错误
避免
避免使用eval()
避免使用with语句,该语句在严格模式中不复存在,可能在未来的ECMAScript标准中也将去除