Note On <High Performance JavaScript>

来源:互联网 发布:windows桌面文件丢失 编辑:程序博客网 时间:2024/05/21 22:53

Chapter 8: 实践技巧


避免双重执行

这个部分讨论的是动态执行的JS代码,通过eval(),Function(),setTimeout()和setInterval()所创建的代码都会经过两次执行的过程,而这导致它们慢很多。


作者的建议是,对于eval()和Function()最好是索性直接避免,而后两者setTimeout()和setInterval(),可以传递预先定义的函数。


====================================================================


使用字面定义

这个问题至少David在【Effective JavaScript】里说过。简单讲就是:

//create an objectvar myObject = new Object();myObject.name = "Nicholas";myObject.count = 50;myObject.flag = true;myObject.pointer = null;//create an arrayvar myArray = new Array();myArray[0] = "Nicholas";myArray[1] = 50;myArray[2] = true;myArray[3] = null;

不如下面执行效率高:

//create an objectvar myObject = {    name: & quot;Nicholas & quot;,    count: 50,    flag: true,    pointer: null};//create an arrayvar myArray = [ & quot;Nicholas & quot;, 50, true, null];


====================================================================


不要重复执行做过的事情

这个部分的例子很经典,判断浏览器和版本,决定执行怎样的代码,通常的写法可能会是:

function addHandler(target, eventType, handler) {    if (target.addEventListener) { //DOM2 Events        target.addEventListener(eventType, handler, false);    } else { //IE        target.attachEvent("on" + eventType, handler);    }}function removeHandler(target, eventType, handler) {    if (target.removeEventListener) { //DOM2 Events        target.removeEventListener(eventType, handler, false);    } else { //IE        target.detachEvent("on" + eventType, handler);    }}


这里判断浏览器的逻辑被重复了。有两个解决方案:


慵懒加载

function addHandler(target, eventType, handler) {    //overwrite the existing function    if (target.addEventListener) { //DOM2 Events        addHandler = function(target, eventType, handler) {            target.addEventListener(eventType, handler, false);        };    } else { //IE        addHandler = function(target, eventType, handler) {            target.attachEvent("on" + eventType, handler);        };    }    //call the new function    addHandler(target, eventType, handler);}function removeHandler(target, eventType, handler) {    //overwrite the existing function    if (target.removeEventListener) { //DOM2 Events        removeHandler = function(target, eventType, handler) {            target.addEventListener(eventType, handler, false);        };    } else { //IE        removeHandler = function(target, eventType, handler) {            target.detachEvent("on" + eventType, handler);        };    }    //call the new 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);    };var removeHandler = document.body.removeEventListener ?    function(target, eventType, handler) {        target.removeEventListener(eventType, handler, false);    } :    function(target, eventType, handler) {        target.detachEvent("on" + eventType, handler);    };

适用于页面加载后要立即执行的功能。


====================================================================


使用执行效率最高的方法


位操作符

在基于32位二进制表达上进行的位运算是最快的,而且其实JS支持这些位操作符:&, |,^和~,甚至>>,<<和>>>。


比如下面的代码:

for (var i = 0, len = rows.length; i < len; i++) {    if (i % 2) {        className = "even";    } else {        className = "odd";    }    //apply class}

换成下面的方案后执行起来会快很多:

for (var i = 0, len = rows.length; i < len; i++) {    if (i & 1) {        className = "odd";    } else {        className = "even";    }    //apply class}


另外还有个位掩码(bitmask)的方案也很经典,这个我曾经在SQL的层面用过:

var OPTION_A = 1;var OPTION_B = 2;var OPTION_C = 4;var OPTION_D = 8;var OPTION_E = 16;var options = OPTION_A | OPTION_C | OPTION_D;//is option A in the list?if (options & OPTION_A) {    //do something}//is option B in the list?if (options & OPTION_B) {    //do something}


原生态方法

就像Math这种內建对象的方法比如Math.acos(x)其实都是在更低的层面上实现的,会快很多。


还有查找DOM元素的两个方法:querySelector()和querySelectorAll()。


Chapter 9: 构建与配置高性能的JavaScript应用程序


这一章讲的东西跟写代码没有直接关系。是在构建大型项目时会用到的构建工具和一些用于优化性能的工具。


这些工具可以做的事情包括:

  • 把若干个JS文件整合成一个JS文件;
  • 有条件性地插入一些代码,比如根据不同开发阶段插入不同用于调试的代码;
  • 修改新版本文件名来解决缓存技术导致的文件更新问题;
  • 上传新版文件至远端服务器,类似CDN;
  • 等等

作者是以Ant为例子展示这些动能的,不过近年来貌似没有人再用Ant了,完全没有听人讨论过。


其他的相关工具和方法还包括:

  • 给JS文件瘦身,用类似YUI Compressor和Packer这样的工具;
  • 在服务器端开启压缩功能,使用gzip这样的编码格式传输文件;
  • 缓存JS文件,避免多余的HTTP请求,
  • 使用CDN这样的分布式工具;
  • 等等。


最后作者推荐一个Yahoo自己的工具:smasher,它能完成大多数上面提到的功能。


Chapter 10: 工具

这一章介绍的工具主要用于两个方面,分析JS程序的性能,和分析页面加载过程的瓶颈。


值得注意的是,有些优化性能的方案是受限于浏览器的,它或许反而导致在其他浏览器上效率变差。


分析性能

YUI Profiler

匿名函数

为了配合性能分析工具,最好还是不要使用匿名函数,而且内联呼叫也不如显式地赋值函数再调用。


比如下面的写法:

myNode.onclick = function() {    myApp.loadData();};

不如换做:

myApp._onClick = function() {    myApp.loadData();};myNode.onclick = myApp._onClick;


寻找被阻滞的脚本文件

Page Speed

依然在发展中。

Fiddler

这个我一直有用。


YSlow

从项目的Git主页来看,最后一次更新是在2014年三月,也就是说它的开发已经被停止三年了,等同于被抛弃的项目。

dynaTrace Ajax Edition

这个工具不是免费的。


顺藤摸瓜找到的一些链接:

15 Website Speed Test Tools for Analyzing Web Performance

Must See JavaScript Dev Tools That Put Other Dev Tools to Shame




0 0
原创粉丝点击