24.1 可维护性
24.1.1 什么是可维护的代码
- 可理解性——其他人可以接手代码并理解它的意图和一般途径,而无需原开发人员的完整解释。
- 直观性——代码中的东西一看就能明白,不管其操作过程多么复杂。
- 可适应性——代码以一种数据上的变化不要求完全重写的方法撰写。
- 可扩展性——在代码架构上已考虑到在未来允许对核心功能进行扩展。
- 可调试性——当有地方出错时,代码可以给予你足够的信息来尽可能直接地确定问题所在。
24.1.2 代码约定
- 可读性
- 函数和方法——每个函数或方法都应该包含一个注释,描述其目的和用于完成任务所可能使用 的算法。
- 大段代码——用于完成单个任务的多行代码应该在前面放一个描述任务的注释。
- 复杂的算法——如果使用了一种独特的方式解决某个问题,则要在注释中解释你是如何做的。
- Hack——因为存在浏览器差异,JavaScript 代码一般会包含一些 hack。
- 变量和函数命名
- 变量名应为名词如 car 或 person。
- 函数名应该以动词开始,如 getName()。返回布尔类型值的函数一般以 is 开头,如isEnable()。
- 变量和函数都应使用合乎逻辑的名字,不要担心长度,就是要见名知意。
- 变量类型透明
24.1.3 松散耦合
- 解耦 HTML/JavaScript
- 解耦 CSS/JavaScript
- 解耦应用逻辑/事件处理程序
24.1.4 编程实践
- 尊重对象所有权
- 不要为实例或原型添加属性;
- 不要为实例或原型添加方法;
- 不要重定义已存在的方法;
- 避免全局量
- 避免与 null 进行比较
- 使用常量
24.2 性能
24.2.1 注意作用域
- 避免全局查找
- 避免 with 语句
24.2.2 选择正确方法
-
避免不必要的属性查找
-
优化循环
- 减值迭代——大多数循环使用一个从 0 开始、增加到某个特定值的迭代器。在很多情况下,从最大值开始,在循环中不断减值的迭代器更加高效。
- 简化终止条件——由于每次循环过程都会计算终止条件,所以必须保证它尽可能快。也就是说避免属性查找或其他 O(n)的操作。
- 简化循环体——循环体是执行最多的,所以要确保其被最大限度地优化。确保没有某些可以被很容易移出循环的密集计算。
- 使用后测试循环——最常用 for 循环和 while 循环都是前测试循环。而如 do-while 这种后测试循环,可以避免最初终止条件的计算,因此运行更快。
-
展开循环
-
避免双重解释
//某些代码求值——避免!!
eval("alert('Hello world!')");
//创建新函数——避免!!
var sayHi = new Function("alert('Hello world!')");
//设置超时——避免!!
setTimeout("alert('Hello world!')", 500);
在以上这些例子中,都要解析包含了 JavaScript 代码的字符串。也就是说必须新启动一个解 析器来解析新的代码。实例化一个新的解析器有不容忽视的开销,所以这种代码要比直接解析慢得多。
- 性能的其他注意事项
- 原生方法较快——只要有可能,使用原生方法而不是自己用 JavaScript 重写一个。
- Switch 语句较快 —— 如果有一系列复杂的 if-else 语句,可以转换成单个 switch 语句则可以得到更快的代码。
- 位运算符较快 —— 当进行数学运算的时候,位运算操作要比任何布尔运算或者算数运算快。
24.2.3 最小化语句数
JavaScript 代码中的语句数量也影响所执行的操作的速度。完成多个操作的单个语句要比完成单个 操作的多个语句快。
- 多个变量声明
//4 个语句——很浪费
var count = 5;
var color = "blue";
var values = [1,2,3];
var now = new Date();
//一个语句
var count = 5,
color = "blue",
values = [1,2,3],
now = new Date();
- 插入迭代值
当使用迭代值(也就是在不同的位置进行增加或减少的值)的时候,尽可能合并语句。请看以下 代码:
var name = values[i];
i++;
// 合并
var name = values[i++];
- 使用数组和对象字面量
24.2.4 优化DOM交互
在 JavaScript 各个方面中,DOM 毫无疑问是最慢的一部分。DOM 操作与交互要消耗大量时间, 因为它们往往需要重新渲染整个页面或者某一部分。
- 使用文档片段fragment来构建 DOM 结构
var list = document.getElementById("myList"),
fragment = document.createDocumentFragment(),
item,
i;
for (i=0; i < 10; i++) {
item = document.createElement("li");
fragment.appendChild(item);
item.appendChild(document.createTextNode("Item " + i));
}
list.appendChild(fragment);
-
对于大的 DOM 更改,使用innerHTML
-
使用事件代理
-
注意 HTMLCollection
24.3 部署
- 为了协助部署,推荐设置一个可以将 JavaScript 合并为较少文件(理想情况是一个)的构建过程。
- 有了构建过程也可以对源代码自动运行额外的处理和过滤。例如,你可以运行 JavaScript 验证器来确保没有语法错误或者是代码没有潜在的问题。
- 在部署前推荐使用压缩器将文件尽可能变小。
- 和 HTTP 压缩一起使用可以让 JavaScript 文件尽可能小,因此对整体页面性能的影响也会最小。