Web篇之JS性能优化
首先,性能优化分好几个方面,本章我们从js方面来优化。
1:垃圾收集
日常中的某些情况下垃圾收集器无法回收无用变量,导致的一个结果就是——内存使用率不断增高,以下为对应的情况以及处理方法。
①对象相互引用会导致引用计数始终为2,所以用完对象后应将引用设为null,例子如下
let element = document.getElementById("test");
let myObject = new Object();
myObject.element = element;
element.someObject = myObject; //....用完后需要加如下代码
myObject.element = null;
element.someObject = null;
②当数据不再有用时,需要通过将值设为null来解除引用,该做法适用于大多数全局变量和全局对象属性,例子如下
function createPerson(name){
let localPerson = new Object();
localPerson.name = name;
return localPerson
} let globalPerson = createPerson("test") //...用完后手动解除
globalPerson = null
③关于与闭包相关的内存泄漏如下
function assignHandler(){
let element = document.getElementById("test");
element.onclick = function(){
alert(element.id)
}
} //以上会导致element的引用数无法被回收,更改如下
function assignHandler(){
let element = document.getElementById("test");
let id = element.id; element.onclick = function(){
alert(id)
}
element = null;
}
2:事件委托
在js中,添加到页面上的事件处理程序数量会直接关系到页面整体运行运行性能。导致这一问题的原因是多方面的。首先函数都是对象,都会占用内存;内存中对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。以下为对应的情况以及处理方法
①同类型的事件处理函数过多时,应该结合为一个,例子如下:
//html代码
<ul id="myLinks">
<li id="goSomeWhere">Go somewhere</li>
<li id="sayHi">Say hi</hi>
</ul> //分别加上事件处理-JS代码
let item1 = document.getElementById("goSomeWhere");
let item2 = document.getElementById("sayHi"); EventUtil.addHandler(item1, "click", function(event){
console.log("goSomeWhere")
} EventUtil.addHandler(item2, "click", function(event){
console.log("sayHi");
} //改善点即将click事件结合在一起
let list = document.getElementById("myLinks") EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
let target = EventUtil.getTarget(event); switch(target.id){
case "goSomeWhere":
console.log("goSomeWhere");
break;
case "sayHi":
console.log("sayHi");
break;
}
}
②内存留有过时不用的“空事件处理程序”也是造成性能问题的主因,两种情况下会造成该问题。运用removeChild()和replaceChild()方法去除节点时;在使用innerHTML替换页面某一部分时,如果带有事件处理程序的元素被innerHTML删除了,那么原有事件处理函数极有可能无法被回收,例子如下
//例子中id为myBtn的点击事件变为了空事件处理程序
<div id="myDiv">
<input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
let btn = document.getElementById("myBtn");
btn.onclick = function(){
document.getElementById("myDiv").innerHTML = "xxxx";
};
</script> //改善点即需要手工移除事件处理程序
<div id="myDiv">
<input type="button" value="Click Me" id="myBtn">
</div>
<script type="text/javascript">
let btn = document.getElementById("myBtn");
btn.onclick = function(){
btn.onclick = null;
document.getElementById("myDiv").innerHTML = "xxxx";
};
</script>
3:注意作用域
关于作用域链,我们明白访问全局变量会比访问局部变量要慢
①若某处循环使用全局变量时,我们可以略做修改,例子如下
//假设有多个img标签的内容,循环中引用了多次document全局变量
function updateUI(){
let imgs = document.getElementsByTagName("img")
for (let i = 0; len = imgs.length; i < len; ++i){
imgs[i].title = document.title + " image “ + i
} let msg = document.getElementById("msg");
msg.innerHTML = "Update";
} //改善点
function updateUI(){
let doc = document
let imgs = doc.getElementsByTagName("img")
for (let i = 0; len = imgs.length; i < len; ++i){
imgs[i].title = doc.title + " image “ + i
} let msg = doc.getElementById("msg");
msg.innerHTML = "Update";
}
②尽量少用with,因为with会增加其中执行代码的作用域链的长度
4:选择正确方法
首先,我们要了解JS中算法的复杂度
标记名称 | 描述 | |
O(1) | 常数 | 不管有多少值,执行的时间都是恒定的。一般表示简单值和存储在变量中的值 |
O(log n) | 对数 | 总的执行时间和值的数量相关,但是要完成算法并不一定要获取每个值。例如:二分查询 |
O(n) | 线性 | 总执行时间和值的数量直接相关。例如:遍历某个数组中的所有元素 |
O(n^2) | 平方 | 总执行时间和值的数量有关,每个值至少要获取n次。例如:插入排序 |
常数值和访问数组元素操作都是O(1)操作;对象属性查找操作是O(n)操作;
如let values = [5, 10]; let sum = values[0] + values[1]属于O(1)操作;let values = window.location.href属于O(2)操作
①遇到有多次属性查询的场合,可以考虑是否能做优化,例子如下
//这里总共做了6次属性查询,其中window.location.href.substring与window.location.href.indexOf分别为3次
let query = window.location.href.subsring(window.location.href.indexOf("?")) //改善, 第一次访问时复杂度会是O(n),但该版本只有4次属性查询,相对于原始版本节省了33%
let url = window.location.href;
let query = url.substring(url.indexOf("?"));
②循环优化,这里其实用后测试循环代替前测试循环会更好,不过本地不采用,例子如下
//原有复杂度为O(n)
for (let i = 0; i < values.length; ++i){
process(values[i]);
} //更改后复杂度为O(1)
for (let i = values.length - 1; i >= 0; --i){
process(values[i])
}
③最小化语句数相关
例如进行多个声明时,我们可以进行组合,例子如下
//多个声明
let count = 5;
let color = "blue";
let values = [1, 2, 3]; //组合成一个
let count = 5,
color = ”blue",
values = [1, 2, 3]
例如插入迭代值时,例子如下
//修改前
let name = values[i];
i++; //修改后
let name = values[i++]
使用数组和对象字面量时,例子如下
//修改前
let values = new Array();
values[0] = 123;
values[1] = 456;
values[2] = 789; let person = new Object();
person.name = "Eric";
person.age = 20; //修改后
let values = [123, 456, 789]
let person = {
name: "Eric",
age:20,
}
④创建DOM节点最好使用innerHTML方法,因为innerHTML设置值时,后台会创建HTML解析器,然后使用内部的DOM调用来创建DOM结构,而非基于JS的DOM调用。
调用一次innerHTML,就会进行一次现场刷新,循环插入DOM结构时,应注意尽量调用少次数的innerHTML,代码如下
//错误方法,做了很多次现场刷新
let list = document.getElementById("myList"),
i; for (i = 0; i < 10; ++i){
list.innerHTML = html+= "<li>Item " + i + "</li>"
} //正确方法,尽管在字符串连接上有性能损失,但却只做了一次现场刷新
let list = document.getElementById("myList"),
html = "",
i; for (i = 0; i < 10; ++i){
html += "<li>Item " + i + "</li>"
} list.innerHTML = html
⑤其他如有多个if-else语句时,应尽可能转为Switch语句;用appendChild()插入元素时,应采用自上而下插入;面向对象编程时,应合理释放内存,设object为null。
Web篇之JS性能优化的更多相关文章
- js 性能优化 篇一
JS性能优化 摘自:http://www.china125.com/design/js/3631.htm 首先,由于JS是一种解释型语言,执行速度要比编译型语言慢得多.(注:,Chrome是第一款内 ...
- js性能优化文章集锦
总结的js性能优化方面的小知识http://www.it165.net/pro/html/201503/35336.html 如何优化你的JS代码http://www.php100.com/html/ ...
- js性能优化-事件委托
js性能优化-事件委托 考虑一个列表,在li的数量非常少的时候,为每一个li添加事件侦听当然不会存在太多性能方面的问题,但是当列表非常的长,长到上百上千甚至上万的时候(当然只是一个解释,实际工作中很少 ...
- 原博客地址http://blog.chinaunix.net/uid/20656672.html不再维护(10年前数百篇oracle/teradata性能优化、故障处理案例)
原博客地址http://blog.chinaunix.net/uid/20656672.html不再维护(数百篇oracle/teradata性能优化.故障处理原创文章) 858871 top 500 ...
- js 性能优化利器:prepack
1. js 性能优化 js 本身是没有像 python 一样的预编译功能,更没有像 java 一样的编译功能,所以,这里所说的 js 代码预编译 只是通过工具实现的类似功能而已. 这就要提到 prep ...
- 从web现状谈及前端性能优化
从web现状谈及性能优化 原文出处:<Karolina Szczur: The State of the Web> 性能优化指南The Internet is growing expone ...
- JS性能优化笔记搜索整理
通过网上查找资料了解关于性能优化方面的内容,现简单整理,仅供大家在优化的过程中参考使用,如有什么问题请及时提出,再做出相应的补充修改. 一. 让代码简洁:一些简略的表达方式也会产生很好的优化 eg:x ...
- 全方位分析web前端如何进行性能优化
前言: 最近刚刚完成项目,空闲一段时间,想起之前有被问起怎么对前端进行性能优化,自己也是脑中零零散散的总不成体系,现特来总结,欢迎补充指教. 1.整体资源 (1)js.css源码压缩 (2)css文件 ...
- 你不知道的Node.js性能优化,读了之后水平直线上升
本文由云+社区发表 "当我第一次知道要这篇文章的时候,其实我是拒绝的,因为我觉得,你不能叫我写马上就写,我要有干货才行,写一些老生常谈的然后加上好多特技,那个 Node.js 性能啊好像 D ...
随机推荐
- jQuery绑定事件的四種方式
这篇文章主要介绍的是jQuery绑定事件的四种方式相关内容,下面我们就与大家一起分享. jQuery绑定事件的四种方式 jQuery提供了多种绑定事件的方式,每种方式各有其特点,明白了它们之间的异同点 ...
- python性能测试脚本-乾颐堂
废话不多说,直接上代码. import httplib import urllib import time import json class Transaction(object): ...
- zip多个分割文件合并
copy /b 1.z01+1.z02+1.zip 注意:1.zip在最后
- 在 macOS 中激活 Astash Professional
Astah Professional v7.2.0-1ff236版安装完毕后,直接用压缩包内的 astah-pro.jar 替换原安装目录内的同名文件(/Applications/astah prof ...
- [Selenium]计算坐标进行拖拽,重写dragAndDropOffset
//@author jzhang6 public void dragAndDropOffset(WebDriver driver,WebElement dragableEl, WebElement d ...
- 12个优秀的国外Material Design网站案例
眼看2017年就快完了,你是不是还没完全搞懂Material Design呢?是嫌说明文档太长,还是觉得自己英文不好?都没关系,小编今天给大家整理了一份干货满满的学习笔记,并列举了一些国外的Mater ...
- oracle 分页其实一个子查询就好了,没理解的自然只能见样学样
.首先rownum是一个查询缓存级别的东西,所以以下写法是错误的 ; 因为rn其实不是student表的内容,看做一个缓存编号就好 但是有些人不服了,加个a.rn<= ;结果还是不行,这下相信了 ...
- ASP.NET MVC与ASP.NET Web API的区别(转)
出处:http://blog.csdn.net/wangzl1163/article/details/72676616 MVC主要用来构建网站,既关心数据也关心页面展示,而Web API只关注数据 W ...
- excel定位函数
在Excel中MATCH函数可以返回指定内容所在的位置,而INDEX又可以根据指定位置查询到位置所对应的数据,各取其优点,我们可以返回指定位置相关联的数据. MATCH函数(返回指定内容所 ...
- CI框架下的PHP增删改查总结
controllers下的 cquery.php文件 <?php class CQuery extends Controller { //构造函数 function CQuery() { par ...