《编写可维护的JavaScript》-读书笔记
编程风格
约定缩进,使用tab或者空格缩进取决于团队的规范。
不要省略分号
行长度80个字符
换行:通常在运算符后换行,下一行增加两个层级的缩进。
空行:为了提高代码的可读性。下面这些情况插入空行
方法之间插入空行
在方法中的局部变量和第一条语句之间
在多行或者单行注释之前
在方法内的逻辑片段之间插入空行
命名:采用驼峰大小写(Camel Case)命名法
UI层的松耦合
将CSS从JavaScript中抽离,尽量在JavaScript中使用CSS的类,而非直接操作style样式。
1 |
|
避免全局变量
全局变量所带来的问题
* 命名冲突
* 增加代码脆弱性:依赖全局变量使得代码和上下文是深耦合。
* 难以测试
要避免意外产生的全局变量
我们都知道,在JavaScript中,如何没有使用var
声明变量的话,那么JavaScript会自动创建一个全局变量。比如下面的例子:
1 |
|
本意应该是声明两个变量,结果不小心将分号输错位逗号,结果就会将title创建成了全局变量。
解决办法
采用单全局变量方式
全文只创建一个全局变量,并将所有的属性和方法都挂载在这个全局对象上。
比如jQuery,定义了$
和jQuery
两个全局对象。只有在$
被其他类库使用了的情况下,为了避免冲突,才应该使用jQuery。
命名空间
即使使用“单全局变量方式”也可能存在着全局污染,所以一般可以使用命名空间来解决。
使用模块
ES6已经可以支持module语法了
“异步模块定义”(AMD)
事件处理
先来看个例子:
1 |
|
在上面这个例子中,应用逻辑(显示popup)和事件处理程序的代码混在一起了。
规则一:隔离应用逻辑
应用逻辑(application logic)指和应用相关的功能性代码,而不是和用户行为相关的。所谓隔离应用逻辑就是将应用逻辑从所有事件处理程序中抽离出来。
比如下面这个例子
1 |
|
规则二:不要分发事件对象
对于上面的代码,showPopup()中,只需要event的两个参数:clientX和clientY。所以不需要将整个event对象作为参数传入,只需要传入所需要的参数即可。如下面代码:
1 |
|
这种思想就是设计模式中所遵循的单一职责原则(SRP),就是一个方法尽量只负责一个功能。将不同的功能细分到不同的方法中。
避免“空比较”
之所以不建议和null
做比较是因为任何有值,任何对象都和null不相等。正确的做法是对于不同类型的值应该采用与之相对应的方法。
检测原始值(string, number, boolean, null, undefined)用typeof
。
typeof
会返回一个表示值的类型。比如
1 |
|
typeof运算符的独特之处在于,将其用于一个未声明的变量也不会报错。对于未声明的变量和值为undefined的变量通过typeof都将返回”undefined”
检测引用值用instanceof
检验自定义类型唯一的方法就是instanceof
检测函数
1 |
|
检测数组
使用ECMAScript5中的方法isArray()
判断
1 |
|
但是由于这个方法可能在低版本浏览器并不兼容,所以可以采用下面的方法进行判断:
1 |
|
检测属性
判断属性是否存在最好的办法就是用in
运算符和hasOwnProperty()
。in
运算符仅仅会简单得判断属性是否存在,而不会去读属性的值。比如:
1 |
|
将配置数据从代码中分离出来
哪些配置数据需要从代码中分离出来:
URL
需要展现给用户的字符串
重复的值
设置值,一些配置参数
任何可能发生变更的值
不同的框架对于保存配置文件的方式各不相同,但思想都是一样,抽离出易变项,单独分离成文件,与代码中的数据和应用逻辑隔离。
抛出自定义错误
在JavaScript中抛出错误是一门艺术。搞清楚代码中哪里适合抛出错误,将有助于在代码发生错误时,大大缩短调试时间。
JavaScript中抛出错误的方法
1 |
|
错误类型
Error,所有错误的基本类型,所有的错误都继承与它。实际上引擎从来不会抛出该类型的错误;
EvalError,通过
eval()
函数执行代码发生错误时抛出;RangeError,一个数字超过边界时抛出;
ReferenceError,期望的对象不存在时抛出,这个错误很常见;
SyntaxError,给
eval()
函数传递的代码中有语法错误时抛出;TypeError,变量不是期望的类型时抛出;
URIError,给encodeURI()、encodeURIComponent()、decodeURI()或者decodeURIComponent()等函数传递格式非法的URI字符串时抛出。