读书笔记(03) - 性能 - JavaScript高级程序设计
作用域链查找
作用域链的查找是逐层向上查找。查找的层次越多,速度越慢。随着硬件性能的提升和浏览器引擎的优化,这个慢我们基本可以忽略。
除了层级查找损耗的问题,变量的修改应只在局部环境进行,尽量避免在局部环境下去操作修改父级变量的值。(react/vue 单向数据流的数据传输方式)
优化方法:声明一个变量存储引用(该方法应用甚多)
不必要的属性查找
// 未优化(window.location.href 3*2 6次)
// 未优化(window.location.href 3*2 6次)
var query = window.location.href.substring(window.location.href.indexOf('?'));
// 优化后(3次,以后多次调用url,查询次数不会增加)
var url = window.location.href;
var query = url.substring(url.indexOf('?'));
url = null;
函数里面声明的变量,在函数调用栈执行后退出时,会自动清除引用。而全局变量和闭包则会与之相反,继续保存,所以使用用后需手动标记清除,以免造成内存泄漏。
优化循环
- 减值迭代
- 简化终止条件
- 简化循环体
- 使用后测试循环
减值迭代
日常应用不多,与增值迭代的区别,就在i存储的值。减值迭代i的值不断在变小,存储的空间也在变小。
但在前端极少需要遍历上万次上亿次的数据,上千上百都很少,所以这个优化可忽略。而且我们遍历的顺序一般都是从数组头部开始,所以增值迭代应用的更多。
// 增值迭代(用的较多)
for(var i = 0; i < len; i++) {
//...
}
// 减值迭代
for(var i = len - 1; i >= 0 ; i--) {
//...
}
简化终止条件 (常用)
终止条件应该是一个固定值判断,应避免在终止条件上做其他运算(属性查找等)。
// 未优化,每次循环都会去计算数组长度
var arr = ['HTML', 'CSS', 'JavaScript'];
for (var i = 0; i < arr.length; i++) {
//...
}
// 优化后
for (var i = 0, len = arr.length; i < len; i++) {
//...
}
// 声明了一个变量len用于储存数组长度,只会计算一次
简化循环体
循环体的代码应该着重于只需要遍历处理的代码,其他无关代码应放置到循环体外面。
后测试循环
最常用的for循环和while循环都是前测试循环。而do-while这种后测试循环,可以避免最初终止条件的计算,因此运行更快。
前测试循环(for/while),可能一次都不会执行循环体
后测试循环(do...while),至少执行一次
用确定索引值更快
// for循环遍历
var arr = ['HTML', 'CSS', 'JavaScript'];
for (let i = 0, len = arr.length; i < len; i++) {
arr[i];
}
// 确定索引值
arr[0];
arr[1];
arr[2];
其他
- 原生方法较快(Math)
- switch语句较快 (多个if情况下)
- 位运算符较快
TIPS: 判断优化,最可能的到最不可能的顺序组织(if/switch
)
最小语句数
符合 write less, do more 的代码追求
多个变量声明合并
// 多个var声明
var name = 'KenTsang';
var age = 28;
var job = 'Developer';
// 合并一个var声明
var name = 'KenTsang',
age = 27,
job = 'Developer';
插入迭代值
// 优化前
var name = value[i];
i++;
// 优化后
var name = value[i++];
数组/对象字面量
创建引用类型可以使用构造函数和字面量两种方式,不过日常习惯都使用字面量,因为语句更简洁,写起来更像数据封装。
// 字面量
var arr = [1, 2, 3, 4];
var obj = {
name: 'KenTsang'
}
// 构造函数
var arr = new Array(1, 2, 3, 4);
var obj = new Object();
obj.name = 'KenTsang';
DOM优化交互
最小现场更新
现场更新:一旦你需要访问的 DOM 部分是已经显示的页面的一部分,那么你就是在进行一个现场更新
文档片段
文档片段相当一个临时的占位符,只有片段中的内容会被添加到DOM上,片段本身并不会被添加。
// 代码片段标签
var ele = document.getElementById('ul');
var fragment = document.createDocumentFragment();
var browsers = ['Firefox', 'Chrome', 'Opera',
'Safari', 'IE'];
browsers.forEach(function(browser) {
var li = document.createElement('li');
li.textContent = browser;
fragment.appendChild(li);
});
// 只会操作一次DOM
ele.appendChild(fragment);
innerHTML
合并插入代码一次性设置innerHTML。
// 优化前:操作多次DOM
var list = document.getElementById("myList");
for (var i=0; i < 10; i++) {
list.innerHTML += "<li>Item " + i + "</li>";
}
// 优化后:操作一次DOM
var innerHtml = '';
for (var i = 0; i < 10; i++) {
innerHtml += '<li>Item' + i + '</li>';
}
list.innerHTML = innerHtml;
事件代理(事件委托)
通过事件流——冒泡机制实现代理,子元素事件触发冒泡到父元素,由父元素绑定一个事件进行统一处理,避免多个事件绑定影响性能。
<ul class="list">
<li class="item">HTML</li>
<li class="item">CSS</li>
<li class="item">JavaScript</li>
</ul>
var listEle = document.getElementById('list');
listEle.addEventListener('click', function(event) {
if (event.target.className.indexOf('item') > -1) {
console.log(event.target.innerHTML);
}
})
// jquery
$('#list').on('click', '.item', function(event){
console.log($(this).html());
})
注意HTMLCollection
任何时候要访问 HTMLCollection,不管它是一个属性还是一个方法,都是在文档上进行一个查询,这个查询开销很昂贵。
// 一个死循环例子
<a href="">link</a>
var existLinkEle = document.getElementsByTagName('a');
for (var i = 0; i < existLinkEle.length; i++) {
console.log(i);
var linkEle = document.createElement('a');
document.body.appendChild(linkEle);
}
// body会不断地插入a标签
因为existLinkEle.length
每次循环都会重新计算页面a节点的数量,而得到的值一直递增。
// 优化(一个变量存储引用)
var len = existLinkEle.length;
for (var i = 0; i < len; i++) {
//...
}
返回HTMLCollection
对象情况有:
document.getElementByTagName()
。- 获取元素的
childNodes
属性 - 获取元素的
attributes
属性 document.forms
,document.images
等
参考文档
作者:以乐之名
本文原创,有不当的地方欢迎指出。转载请指明出处。
读书笔记(03) - 性能 - JavaScript高级程序设计的更多相关文章
- 读书笔记(05) - 事件 - JavaScript高级程序设计
HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...
- 读书笔记(02) - 可维护性 - JavaScript高级程序设计
编写可维护性代码 可维护的代码遵循原则: 可理解性 (方便他人理解) 直观性 (一眼明了) 可适应性 (数据变化无需重写方法) 可扩展性 (应对未来需求扩展,要求较高) 可调试性 (错误处理方便定位) ...
- 读书笔记(01) - JSON - JavaScript高级程序设计
JSON与JavaScript对象 JSON是一种表示结构化数据的存储格式,语法格式上与JavasScript对象有些类似. TIPS: 与JavaScript对象的格式区别 不支持变量.函数或对象实 ...
- 学习笔记:《JavaScript高级程序设计》
第1章 JavaScript简介 1.一个完整的JavaScript实现应该由三部分组成:核心(ECMAScript),文档对象模型(DOM)和浏览器对象模型(BOM). 2.Web浏览器只是ECMA ...
- 《JavaScript高级程序设计》读书笔记--前言
起因 web编程过程使用javascript时感觉很吃力,效率很低.根本原因在于对javascript整个知识体系不熟,看来需要找些书脑补一下,同时欢迎众网友监督. 大神推荐书籍 看了博客大神们推荐的 ...
- 《Javascript高级程序设计》读书笔记之对象创建
<javascript高级程序设计>读过有两遍了,有些重要内容总是会忘记,写一下读书笔记备忘 创建对象 工厂模式 工厂模式优点:有了封装的概念,解决了创建多个相似对象的问题 缺点:没有解决 ...
- JavaScript高级程序设计(读书笔记)(一)
本笔记汇总了作者认为“JavaScript高级程序设计”这本书的前七章知识重点,仅供参考. 第一章 JavaScript简介 JavaScript发展简史: 1995年,JavaScript诞生 19 ...
- 读书笔记(06) - 语法基础 - JavaScript高级程序设计
写在开头 本篇是小红书笔记的第六篇,也许你会奇怪第六篇笔记才写语法基础,笔者是不是穿越了. 答案当然是没有,笔者在此分享自己的阅读心得,不少人翻书都是从头开始,结果永远就只在前几章. 对此,笔者换了随 ...
- (读书笔记)函数参数浅析-JavaScript高级程序设计(第3版)
ECMAScript函数不介意传递的参数个数,因为在其内部是用一个数组进行表示的.在函数体内可以通过arguments对象来访问这个参数数组,就像我们正常访问数组一样处理. arguments对象只是 ...
随机推荐
- AngularJS的$location基本用法和注意事项
一.配置config app.config([ '$locationProvider', function($locationProvider) { $locationProvider.html5Mo ...
- 20155205 《Java程序设计》0510课上实践博客
20155205 <Java程序设计>0510课上实践博客 一.教材代码检查-p98 未提交成功原因: 一开始在iterm中运行,但是结果出错,没有时间提交了.这个提交其实很简单,没有提交 ...
- 2018-01-13 view绘制流程-activity启动流程-window-decorView-ViewRootImpl关系
1.activity启动流程: https://www.jianshu.com/p/927ca995bca6 http://blog.csdn.net/qian520ao/article/detail ...
- Matlab绘图添加直角坐标轴
绘制y=x^2,并添加直角坐标轴. clear;clc;close all %% 绘制方程 x = -10:0.01:10; figure; y = x.^2-30; plot(x,y,'k','li ...
- AFNetworking网络请求数据
//创建AFNetworking的请求操作 AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWit ...
- linux下如何编写shell脚本
我对shell脚本的认识,除了执行过同事写的shell 脚本外,其他一无所知,为了让自己强大,我决定自己研究shell脚本,也许在你看来很简答,没必要说这么多废话,但是我希望在我的技术log里记录下来 ...
- java静态代码块、普通代码
参考文章:http://www.cnblogs.com/qinpengming/p/5227227.html Java中经常有一些静态块,这是用来在生成类之前进行的初始化,无论java还C++语言中的 ...
- Flink的入门
Apache Flink(下简称Flink)项目是大数据处理领域最近冉冉升起的一颗新星,其不同于其他大数据项目的诸多特性吸引了越来越多人的关注.本文将深入分析Flink的一些关键技术与特性,希望能够帮 ...
- ExternalException (0x80004005): GDI+ 中发生一般性错误
.net开发的程序用了一个自绘的框架, 平常部署到IIS上都没有问题,今天突然之间这个功能就运行不起来了. 报错:GDI+错误,然后在本地的VS里面运行是没有问题的 百度出来的改Path环境变量.注册 ...
- KNIME + Python = 数据分析+报表全流程
Python 数据分析环境 数据分析领域有很多可选方案,例如SPSS傻瓜式分析工具,SAS专业性商业分析工具,R和python这类需要代码编程类的工具.个人选择是python这类,包括pandas,n ...