信息谷 - ICITU

标题: 高性能JavcaScript(一) [打印本页]

作者: sxadmin    时间: 2021-10-25 10:25
标题: 高性能JavcaScript(一)
本系列是《高性能javascript》读书笔记和一些自己的思考整理,一共两篇,一来可以作为自己的总结;二来可以加深对知识的理解;三可以方便后期知识的整理。

第一章、加载和执行

1、将所有的</script>标签都放在<body>中,并放在末尾;

2、尽量减少</script>脚本的数量,相应速度将会更快;

3、无阻塞得秘诀在于,在页面娇在完成后才加载javascript代码。意味着在window对象的load事件触发后再下载脚本。

有多种无阻塞下载Javascript的方法:

使用标签的defer和async属性;
使用动态创建的</script>元素来下载并执行代码;
使用XHR对象加载Javascript代码并注入页面中。
推荐的无阻塞模式:

1、先添加动态加载所需的代码;

2、然后加载初始化页面所需的剩下的代码。

function loadScript(url, callback){
    var script = document.createElement("script");
    script.type = "text/javascript";
    if(script.readyState){ // IE
        script.onreadystatechange = function(){
            if(script.readyState == "loaded" || script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    }else{ // FF, Chrome, Opera, ...
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}
1、将下面的代码放在</body>闭合标签前面

<script type="text/javascript" src="load.js">
<script type="text/javascript">
    loadScript("the-rest.js",function(){
        Application.init();
    });
</script>
上面的代码有两个优势:

a、确保不会阻塞脚本

b、当第二个js文件下载时需要的所有dom已经构建完毕,并做好了交互准备,避免需要另一个时间来检测页面是否准备好。

2、把loadScript()函数直接嵌入页面,从而避免多产生一次http请求。

<script type="text/javascript">
function loadScript(url, callback){
    var script = document.createElement("script");
    script.type = "text/javascript";
    if(script.readyState){ // IE
        script.onreadystatechange = function(){
            if(script.readyState == "loaded" || script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    }else{ // FF, Chrome, Opera, ...
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript("the-rest.js",function(){
        Application.init();
    });
</script>

采用第二种方式,可以用YUI压缩代码。
第二章、数据存取

1、数据共有四种存储方式:字面量、变量、数组项和对象;

2、访问字面量和变量速度最快,因为全局变量总是存在于执行上下文作用域链的最末端,所以尽量用局部变量;

3、避免使用with语句和try-catch子句,因为会改变对象的作用域链,会使查找的层级变深,会对性能有影响;

闭包对性能的影响:

a、当外部函数创建时,闭包没变化;

b、当外部函数执行时,闭包被创建,并初始化为外部函数的活动对象;

c、当闭包执行时,创建执行上下文,闭包自身又创建一个活动对象。

若频繁访问闭包外部变量,可设置一个局部变量存储外部变量,减轻闭包对性能的损失。

4、避免嵌套,包括对象的嵌套和if-else的嵌套;

5、属性和方法在原型链中的位置越深,访问他的速度就越慢;

6、可以将常用的对象成员、数组、跨域变量保存在局部变量中来改善性能。

第三章、DOM编程

1、最小化DOM访问次数,尽量在JS端处理;

修改页面区域的最佳方案,即innerHTML对性能影响:webkit中DOM>innerHTML;非webkit中DOM<innerHTML.

2、如需访问某个DOM节点,使用局部变量保存其引用,获取DOM元素时,在IE中nextSibling比childNode表现优异,其他浏览器二者运行时间几乎相等,在所有浏览器中,children比childNodes要快,大约为1.5-3倍;

3、HTML集合类似数组,但只能用length方法和下标索引,无其他方法,小心使用;

4、使用速度最快的API,如querySelectororAll()和firstElementChild();

5、留意重绘和重排,离线操作DOM树,使用缓存,并减少访问儿女局部信息的次数;

重绘与重排过程

a、下载所有组件html、css、js、图片;

b、解析并生成DOM树和渲染树(隐藏的dom元素在渲染树中没有对应的节点);

c、绘制页面元素;

d、DOM变化影响了元素几何属性,导致重排

e、只要DOM发生变化,一定会重绘。

最小化重绘和重排方法:

a、cssText复制/追加,一次完成多次css赋值操作;

b、css的classname。

批量修改DOM:

(1)使元素脱离文档流

(2)对其应用多重改变

(3)把元素带回文档中

有三种方式可以使dom脱离文档:

a、隐藏元素,应用修改,重新显示;

b、使用文档片断在当前的DOM之外构建一个子树,再把它拷贝回文档;

c、将原始元素拷贝到一个脱离文档的节点,修改副本,完成后再替换原始元素。

6、动画中尽量使用绝对定位,使用拖放代理;

7、使用时间代理减少事件处理器的数量。

第四章、算法和流程控制

1、for-in性能较差于其余三种循环,只适合用于一个属性未知的集合;

2、尽量较少迭代的运算量和减少循环迭代次数;

3、通常switch比ifelse快,当判断条件较多时,使用查找表;

4、注意浏览器中的调用栈大小;

5、遇到栈溢出错误,讲方法改为迭代,或者使用Memoization来避免重复计算。






欢迎光临 信息谷 - ICITU (https://www.icitu.com/) Powered by Discuz! X3.4