JavaScript 性能优化
加载和执行
1、 </body>
闭合标签之前,将所有的<script>
标签放在页面底部,确保在脚步执行之前页面已经完成渲染。
2、 合并脚本。下载单个 100KB 的文件将比下载 4 个 25KB 的文件更快,因此页面标签的<script>
标签越少,加载也就越快,响应也越迅速。无论外链文件或者内嵌脚本。
3、 使用无阻塞下载 javascript
的方法,即在页面加载完成后才加载 Javascript
代码,以下有几种无阻塞下载方法:
- 使用
<script>
的defer
属性(只有 IE4+和 FireFox3.5+支持)
<script src="file.js" defer></script>
使用动态创建的
<script>
元素来下载并执行代码// 通过监听script元素接收完成事件来获得脚本加载完成时的状态
// 封装标准和IE特有的实现方法函数
function loadscript(url, callback) {
let script = document.createElement('script');
if (script.readyState) {
//IE
script.onreadystatechange = function() {
if (
script.readyState === 'loaded' ||
script.readyState === 'complete'
) {
script.onreadystatechange = null;
callback();
}
};
} else {
// 其他浏览器
scripy.onload = function() {
callback();
};
}
script.src = url;
document.getElementsByTagName('head')[0].appendchild(script);
}
// 使用上述封装函数加载文件
loadscript('file.js', function() {
console.log('file is loaded ~');
});使用 XHR 对象下载
javascript
代码并注入页面中let xhr = new XMLHttpRequest();
xhr.open('get', 'file.js', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
let script = document.createElement('script');
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
总结:
向页面中添加大量 JavaScript
的推荐做法:先添加动态加载所需代码,然后加载初始化页面所需剩下代码
数据存储
1、访问字面量和局部变量的速度比访问数组元素和对象成员快,因此尽量使用字面量和局部变量,减少数组项和对象成员的使用。
2、尽可能使用局部变量。如果某个跨作用域的值在函数中被引用一次以上,把它存储到局部变量中。
// 不推荐
function initFn() {
// document.getElementById('myImg')多次被引用
document.getElementById('myImg').src = 'photo.png';
document.getElementById('myImg').alt = 'photo';
} // 推荐
function initFn() {
// 改写
let myImg = document.getElementById('myImg');
myImg.src = 'photo.png';
myImg.alt = 'photo';
}
3、避免使用 with 语句,它会改变执行环境作用域链。try-catch 中的 catch 也有同样的影响,看实际情况中进行运用。
4、属性和方法在原型链中的位置越深,访问的速度越慢
总结:
把常用的对象成员、数组元素、跨域变量保存在局部变量中
DOM
1、最小化 DOM 访问次数,如果需要多次访问某个 DOM 节点,使用局部变量存储它的引用。
// 不推荐
function innerHTMLLoop(){
for(let i = 0; i < 5; i++){
document.getElementById('myDiv').innerHTML += 'a';
}
} // 推荐
function innerHTMLLoop(){
let content = '';
for(let i = 0; i < 5; i++){
content += 'a';
}
document.getElementById('myDiv').innerHTML = content;
}
2、如果需要在迭代中使用 HTML 集合,把它的长度缓存到一个变量中;如果需要多次操作集合,把它拷贝到一个数组中。
HTML 集合有
document.getElementsByName()
,document.getElementsClassName()
,document.getElementsByTagName()
,document.images
,document.links
,document.forms
等等,返回的是类似数组的列表,但是它以一种“假定实时态”实时存在,即当底层文档对象更新时,它也会自动更新。// 死循环
let divs = document.getElementsByTagName('div');
for (let i = 0; i < divs.length; i++) {
document.body.appendChild(document.createElement('div'));
}当遍历一个集合时,把集合存储在局部变量中,并把 length 缓存在循环外部
// 推荐
function collectNodes() {
let coll = document.getElementsByTagName('div');
let len = coll.length;
let nodeName = '';
let tagName = '';
let el = null;
for (let i = 0; i < len; i++) {
el = coll[i];
nodeName = el.nodeName;
tagName = el.tagName;
}
return { nodeName, tagName };
}
3、减少重绘和重排,批量修改样式时,“离线”操作 DOM
树,使用缓存,并减少访问布局信息的次数。
当页面布局和几何属性改变时需要“重排”。下列情况均会发生“重排”:
1、添加或删除可见的
DOM
元素2、元素位置发生改变
3、元素尺寸改变(包括:外边距、内边距、边框厚度、宽度、高度等属性改变)
4、内容改变,如文本改变或图片被另一个不同尺寸的图片代替
5、页面渲染器初始化
6、浏览器窗口改变
完成“重排”后,浏览器会重新绘制受影响的部分到屏幕中,过程为“重绘”。
减少“重绘”和“重排”
1、使元素脱离文档流
2、对其应用多次改变
3、把元素带回文档中
// 第一种方式:隐藏元素,应用修改,重新显示
let ul = document.getElementById('nyList');
ul.style.display = 'none';
// 向ul中添加附加数据
appendDataToElement(ul, data);
ul.style.display = 'block'; // 第二种方式:使用文档片段(document fragment)在当前DOM之外构建一个子树,再把它拷贝到文档(推荐)
let fragment = document.createDocumentFragment();
// 向fragment中添加附加数据
appendDataToElement(ul, data);
document.getElementById('myList').appendChild(fragment); // 第三种方式:将原始元素拷贝到一个脱离文档的节点中,修改副本,完成后再替换原始元素
let old = document.getElementById('myList');
let clone = old.cloneNode(true);
// 向clone中添加附加数据
appendDataToElement(ul, data);
old.parentNode.replaceChild(clone, old);
4、使用事件委托减少事件处理器的数量
// Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用ev.target,IE浏览器用event.srcElement。
myLi.onclick = function(e) {
let e = e || window.event;
let target = ev.target || ev.srcElement;
if (target.nodeName.toLowerCase() == 'li') {
alert(target.innerHTML);
}
};
算法和流程控制
- 选择时间复杂度低的算法
- 避免使用 for-in 循环,除非需要遍历一个属性数量未知的对象
- 使用 if-else 要确保最可能出现的条件放在首位,条件数量大时,优先使用 switch
- 使用查找表。查找表相对于 if-else 和 switch,不近速度快,而且可读性好
// 将返回值集合存入数组
let results = [result0,result1,result2,result3,result4,result5,result6,result7,result8,result9,result10,];
// 返回当前结果
return results[value];
构建和部署
合并 JavaScript 文件以减少 HTTP 请求数
使用 webpack 压缩 JavaScript 文件
使用 CDN 提供 JavaScript 文件;CDN 不仅可以提升性能,也会为你管理文件的压缩和缓存
参考:图灵图书《高性能JavaScript》
JavaScript 性能优化的更多相关文章
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- javascript性能优化-repaint和reflow
repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲 ...
- 摘:JavaScript性能优化小知识总结
原文地址:http://www.codeceo.com/article/javascript-performance-tips.html JavaScript的性能问题不容小觑,这就需要我们开发人员在 ...
- Javascript 性能优化的一点技巧
把优秀的编程方式当成一种习惯,融入到日常的编程当中.下图是今天想到的一点Javascript 性能优化的技巧,分享一下,抛砖引玉.
- JavaScript性能优化小窍门汇总(含实例)
在众多语言中,JavaScript已经占有重要的一席之地,利用JavaScript我们可以做很多事情 , 应用广泛.在web应用项目中,需要大量JavaScript的代码,将来也会越来越多.但是由于J ...
- JavaScript性能优化小知识总结(转)
JavaScript的性能问题不容小觑,这就需要我们开发人员在编写JavaScript程序时多注意一些细节,本文非常详细的介绍了一下JavaScript性能优化方面的知识点,绝对是干货. 前言 一直在 ...
- JavaScript性能优化篇js优化
JavaScript性能优化篇js优化 随着Ajax越来越普遍,Ajax引用的规模越来越大,Javascript代码的性能越来越显得重要,我想这就是一个很典型的例子,上面那段代码因为会被频繁使用, ...
- JavaScript 性能优化技巧分享
JavaScript 作为当前最为常见的直译式脚本语言,已经广泛应用于 Web 应用开发中.为了提高Web应用的性能,从 JavaScript 的性能优化方向入手,会是一个很好的选择. 本文从加载.上 ...
- javascript性能优化之避免重复工作
javascript最重要也最根本的性能优化标准之一是避免工作,避免工作又包括两点,第一,不做不必要的工作,第二,不做重复的已经完成的工作.第一部分可以通过代码重构完成,第二部分不做重复的工作有时候难 ...
- javascript性能优化:创建javascript无阻塞脚本
javaScript 在浏览器中的运行性能,在web2.0时代显得尤为重要,成千上万行javaScript代码无疑会成为性能杀手, 在较低版本的浏览器执行JavaScript代码的时候,由于浏览器只使 ...
随机推荐
- C#操作计划任务
昨天有一个任务,就是要下载相关文件,然后保存在相关路径下,这个没什么难度,所以就略过不谈,主要谈谈定时下载,即每天某个固定时间执行下载,这个功能我是用C#代码来操作windows自带的任务计划来实现的 ...
- CI中site_url和base_url的区别
你若使用site_url("test/php/1");则实际url为 http://domain.com/index.php/test/php/1 若使用base_url(&quo ...
- Skype SILK vs. iLBC vs. Speex
对比一下这三种VOIP语音算法的特点: 1 参数与特征 2 SILK性能 关于iLBC和Speex的性能可以参考以前写的文章. 3 关于VOIP一些观点(仅代表个人观点) 1) Skype 辛苦三年 ...
- Agc011_F Train Service Planning
先放题面,再放LHX巨佬题解 接着就是%%%.$orz.Oro.Or2.Otz.OTL.sto.rzo.Jto$.On_.○| ̄|_啊 模拟赛里直接把这道题刚掉了 一题升天·爆踩全场 这题思维跨越度已 ...
- bzoj 3998 弦论 —— 后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 关于相同子串算一个还是算多个,其实就是看一种状态的 right 集合是否加上 Pare ...
- 杂项:grunt-tmod
ylbtech-杂项:grunt-tmod 前端模板预编译工具 tmodjs 的grunt自动化插件. 1.返回顶部 1. grunt-tmod 前端模板预编译工具 tmodjs 的grunt自动化插 ...
- FATFS 文件系统
转载请注明出处:http://blog.csdn.net/qq_26093511/article/details/51706228 1.文件系统是什么? 负责管理和存储文件信息的软件机构称为文件管理系 ...
- Ajax调用后台方法报未定义
需要在web.config中<system.webServer>节点下添加如下内容 <handlers> <add name="ajax" verb= ...
- linux日常管理-linux日志
通过系统日志获得相关信息,出现错误,突发情况可以通过查看日志获得有用的信息.遇到故障,看日志是最常用的方法,在日常工作中一定要养成看日志的习惯. 最核心的日志在这个目录下 日志会无限生成,占用的内存会 ...
- 双飞翼布局介绍-始于淘宝UED
仔细分析各种布局的技术实现,可以发现下面三种技术被经常使用: 浮动 float 负边距 negative margin 相对定位 relative position 这是实现布局的三个最基本的原子技术 ...