首先,性能优化分好几个方面,本章我们从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性能优化的更多相关文章

  1. js 性能优化 篇一

    JS性能优化 摘自:http://www.china125.com/design/js/3631.htm  首先,由于JS是一种解释型语言,执行速度要比编译型语言慢得多.(注:,Chrome是第一款内 ...

  2. js性能优化文章集锦

    总结的js性能优化方面的小知识http://www.it165.net/pro/html/201503/35336.html 如何优化你的JS代码http://www.php100.com/html/ ...

  3. js性能优化-事件委托

    js性能优化-事件委托 考虑一个列表,在li的数量非常少的时候,为每一个li添加事件侦听当然不会存在太多性能方面的问题,但是当列表非常的长,长到上百上千甚至上万的时候(当然只是一个解释,实际工作中很少 ...

  4. 原博客地址http://blog.chinaunix.net/uid/20656672.html不再维护(10年前数百篇oracle/teradata性能优化、故障处理案例)

    原博客地址http://blog.chinaunix.net/uid/20656672.html不再维护(数百篇oracle/teradata性能优化.故障处理原创文章) 858871 top 500 ...

  5. js 性能优化利器:prepack

    1. js 性能优化 js 本身是没有像 python 一样的预编译功能,更没有像 java 一样的编译功能,所以,这里所说的 js 代码预编译 只是通过工具实现的类似功能而已. 这就要提到 prep ...

  6. 从web现状谈及前端性能优化

    从web现状谈及性能优化 原文出处:<Karolina Szczur: The State of the Web> 性能优化指南The Internet is growing expone ...

  7. JS性能优化笔记搜索整理

    通过网上查找资料了解关于性能优化方面的内容,现简单整理,仅供大家在优化的过程中参考使用,如有什么问题请及时提出,再做出相应的补充修改. 一. 让代码简洁:一些简略的表达方式也会产生很好的优化 eg:x ...

  8. 全方位分析web前端如何进行性能优化

    前言: 最近刚刚完成项目,空闲一段时间,想起之前有被问起怎么对前端进行性能优化,自己也是脑中零零散散的总不成体系,现特来总结,欢迎补充指教. 1.整体资源 (1)js.css源码压缩 (2)css文件 ...

  9. 你不知道的Node.js性能优化,读了之后水平直线上升

    本文由云+社区发表 "当我第一次知道要这篇文章的时候,其实我是拒绝的,因为我觉得,你不能叫我写马上就写,我要有干货才行,写一些老生常谈的然后加上好多特技,那个 Node.js 性能啊好像 D ...

随机推荐

  1. Python爬虫进阶一之爬虫框架概述

    综述 爬虫入门之后,我们有两条路可以走. 一个是继续深入学习,以及关于设计模式的一些知识,强化Python相关知识,自己动手造轮子,继续为自己的爬虫增加分布式,多线程等功能扩展.另一条路便是学习一些优 ...

  2. [Training Video - 5] [Groovy Script Test Step - Collections, Exceptions] HashSet and Hashtable

    Hashset: HashSet set = new HashSet() set.add("India") set.add("USA") set.add(&qu ...

  3. Zookeeper 源码(三)Zookeeper 客户端源码

    Zookeeper 源码(三)Zookeeper 客户端源码 Zookeeper 客户端主要有以下几个重要的组件.客户端会话创建可以分为三个阶段:一是初始化阶段.二是会话创建阶段.三是响应处理阶段. ...

  4. popupWindow自适应大小

    // popupWindow自适应大小 popupWindow = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP ...

  5. C++中static修饰的静态成员函数、静态数据成员

    1.静态成员函数.静态数据成员 在类中,用static修饰的成员函数被称为静态成员函数,而用static修饰的数据成员就称为静态数据成员:与普通的成员函数和数据成员不同, 静态成员函数和静态数据成员有 ...

  6. Redis-3.2.0集群配置(redis cluster)

    版本:redis-3.0.5 redis-3.2.0  redis-3.2.9  redis-4.0.11 参考:http://redis.io/topics/cluster-tutorial. 目录 ...

  7. linux每天一小步---rm命令详解

    1 命令功能 rm命令用于删除文件或者目录,值得注意的是linux下的删除不弯曲等同于windows系统下的删除操作,linux系统下一旦删除了文件或者目录那么它将消失,而windows系统下我们还可 ...

  8. 阿里杨传辉的访问节选(oceanbase)

    皮皮(Q4): OceanBase第一个应用是收藏夹.最近,听说支付宝交易也用到了OceanBase.能否结合阿里的应用谈谈OceanBase的优势. 杨传辉(A4):相比传统的关系数据库,谈及Oce ...

  9. 无线破解那点事(PJ)

    有一段时间没有写博客了.只能说苦逼学生党伤不起啊,还好没挂-废话不说了,近期将会讲讲无线PJ那点事,也不是啥干货,就一些先前的笔记分享把. 0.无线网卡 想要提高破解效率,一块猛一点的USB无线网卡是 ...

  10. Lucene4:获取中文分词结果,根据文本计算boost

    1. 要求 环境: Lucene 4.1版本/IKAnalyzer 2012 FF版本/mmseg4j 1.9版本 实现功能: 1).给定输入文本,获取中文拆分词结果:2).给定输入文本,对该文本按一 ...