# JavaScript编程实践过程中性能的优化

> 每种编程语言都有它的“痛点”，并且随着时间的推移，它存在的低效模式也不断发展。JavaScript提出了一些独一无二的性能挑战，这与你代码组织的方式有关，随着Web应用变得越来越高级，包含的JavaScript代码也越来越多，各种模式与反模式也逐渐出现，为了编写更高效的代码，请牢记这些编程实践 ...

- 发布日期: 2015-02-16
- Author: Tw93
- HTML: https://tw93.fun/2015-02-16/High-Performance-JavaScript-7.html
- English translation: https://tw93.fun/en/2015-02-16/High-Performance-JavaScript-7.md
- 全部文章: https://tw93.fun/posts.md

---

每种编程语言都有它的“痛点”，并且随着时间的推移，它存在的低效模式也不断发展。JavaScript提出了一些独一无二的性能挑战，这与你代码组织的方式有关，随着Web应用变得越来越高级，包含的JavaScript代码也越来越多，各种模式与反模式也逐渐出现，为了编写更高效的代码，请牢记这些编程实践：

### 避免多重求值（Double Evaluation）
通过避免使用eval()和function()构造器来避免双重求值带来的性能消耗，同样的，给setTimeout()和setInterval()传递函数而不是字符串作为参数。
双重求值是一项代价昂贵的操作，它比直接包含代码执行速度要慢很多。

### 使用Object/Array直接量
在JavaScript中创建对象和数组的方法有很多，但使用对象和数组直接量是最快的方式，而且直接量可以有助于节省代码量，以减少整个文件的尺寸。
```javascript
//创建一个对象
var myObject = {
    name: "Lucy",
    age: 21,
    count: 50
};

//创建一个数组
var myArray = ["Lucy", 21, 50];
```

### 不要重复工作
在计算机科学领域中最主要的优化技术之一是“避免无谓的工作(work avoidance)”。
避免无谓的工作的概念有两重意思：**别做无关紧要的工作**，**别重复做已经完成的工作**。

#### 延迟加载
第一种消除函数中的重复工作的方法是延迟加载(lazy loading)。延迟加载意味着在信息被使用前不会做任何操作，当一个函数在页面中不会立刻调用时候，延迟加载是最好的选择。

#### 条件预加载  
它会在脚本加载期间提前检测，而不会等到函数被调用，检测的操作依然只有一次，只是过程来得更早。条件预加载确保所有函数调用消耗的时间相同，其代价是需要脚本加载时就检测，而不是加载后，预加载适用于一个函数马上用到，并且在整个页面的生命中频繁出现的场合。

### 使用速度快的部分

#### 位操作
有好几种方法来利用为创造·位操作符提升JavaScript的速度。

 - 使用运算代替纯数学操作  
  ```javascript
        //通常采用对2取模的方式实现表格颜色交换
    for (var i = 0, len = rows.length; i < len; i++) {
        if (i % 2) {
            className = "even";
        } else {
            className = "odd";
        }
    }

    //通过使用位运算的方式，比原来版本快了50%(取决于浏览器)
    for (var i = 0, len = rows.length; i < len; i++) {
        if (i & １) {
            className = "even";
        } else {
            className = "odd";
        }
    }
  ```

 - 使用“位掩码”  
    位掩码是计数机科学中一种常用的技术，用于处理同时存在多个布尔选项的情况，其思路是使用单个数字的每一位来判定是否选项成立，从而有效地数字转换为布尔值标记组成的数组。掩码中每个选项的值都等于2的幂。
    例如：
  ```javascript
         var OPTION_A = 1;
         var OPTION_B = 2;
         var OPTION_C = 4;
         var OPTION_D = 16;
         //通过定于这些选项，你可以用按位或运算创建一个数字来包含多个设置选项
         var options = OPTION_A | OPTION_C | OPTION_D;
         //然后通过按位与操作判断一个给定的选项是否可用
         //如果该选项未设置，则结果为0，反之为1

         //选项A是否在列表中？
         if (options & OPTION_A) {
             //代码处理
         }

         //像这样掩码运算速度非常快
    ```

#### 原生方法
无论你的代码如何优化，都永远比不过JavaScript引擎提供的原生方法更快。对于进行数学运算可以通过使用**内置的Math对象**会更快。还有对于选择器API，当原生方法可以使用时，应该尽量使用它们。
