第8章:编程实践

避免双重求值

JS运行在程序中提取一个包含代码的字符串,然后动态执行它。有四种标准法可以实现:eval()Function()构造函数、setTimeout()setInterval()。其中每个方法都允许传入一个JS代码字符串并执行它。

当在JS代码中执行另一段JS代码时,都会导致双重求值的性能消耗。在实际项目中,避免使用eval()Function(),而对于setTimeout()setInterval(),建议传入函数而不是字符串来作为第一个参数。

避免双重求值是实现JS运行期性能最优化的关键所在。

使用Object/Array直接量

JS创建对象和数组的方法中,对象和数组直接量是最快的方式。

//创建一个对象
var obj = {
    name: 'Andy',
    count: 5,
    flag: true,
    pointer: null
};

//创建一个数组
var arr = ['Andy', 50, true, null];

避免重复工作

最常见的重复工作就是浏览器探测。典型的跨浏览器代码写法:

function addHandler(target, eventType, handler) {
    if (target.addEventListener) {
        target.addEventListener(eventType, handler, false);
    } else {
        target.attachEvent("on" + eventType, handler);
    }
}

function removeHandler(target, eventType, handler) {
}

延迟加载

第一种消除函数中的重复工作的方法时延迟加载。采用延迟加载的函数版本:

function addHandler(target, eventType, handler) {
    if (target.addEventListener) {
        addHandler = function (target, eventType, handler) {
            target.addEventListener(eventType, handler, false);
        }
    } else {
        addHandler = function (target, eventType, handler) {
            target.attachEvent("on" + eventType, handler);
        }
    }
    //调用新函数
    addHandler(target, eventType, handler);
}

function removeHandler(target, eventType, handler) {
}

当一个函数在页面中不会立刻调用时,延迟加载是最好的选择。

条件预加载

条件预加载会在脚本加载期间提前检测,而不会等到函数被调用。

var addHandler = document.body.addEventListener ?
    function (target, eventType, handler) {
        target.addEventListener(eventType, handler, false);
    } : function (target, eventType, handler) {
        target.attachEvent("on" + eventType, handler);
    };

条件预加载适用于一个函数马上就要被用到,并且在整个页面的生命周期中频繁出现的场合。

使用速度快的部分

位操作

JS中的数字都以64位格式存储。在位操作中,数字被转换为有符号的32位格式。每次运算符都会直接操作该32位数以得到结果。

AND按位与

两个操作数的对应位都是1时,该位返回1。

OR按位或

两个操作数的对应位只要有一个是1时,该位返回1。

XOR按位异或

两个操作数的对应位只有一个时1时,该位返回1。

NOT按位取反

遇到0则返回1,反之亦然。

采用对2取模运算实现表格行颜色交替。通过让给定数字与数字1进行按位与运算进行判断。

for (var i = o, len = rows.length; i < len; i++) {
    if (i & 1) {//对2取模运算 if (i % 2) {}
        className = "even";
    } else {
        className = "odd";
    }
    //增加class
}

改进后的按位与操作比对2取模操作快了50%

第二种使用位运算的技术称为位掩码。其思路是使用单个数字的每一位来判断是否选项成立,从而有效地把数字转换为布尔值标记组成的数组。掩码中的每个选项的值都等于2的幂。

JS也支持按位左移<<,按位右移>>和无符号右移等位运算符。

原生方法

原生的querySelector()querySelectorAll()方法完成任务平均所需时间是基于JS的CSS查询的10%。

当原生方法可用时,尽量使用它们。特别是数学运算和DOM操作。

小结

为了编写更高效的代码,使用以下编程实践: