作用域链查找

作用域链的查找是逐层向上查找。查找的层次越多,速度越慢。随着硬件性能的提升和浏览器引擎的优化,这个慢我们基本可以忽略。

除了层级查找损耗的问题,变量的修改应只在局部环境进行,尽量避免在局部环境下去操作修改父级变量的值。(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;

函数里面声明的变量,在函数调用栈执行后退出时,会自动清除引用。而全局变量和闭包则会与之相反,继续保存,所以使用用后需手动标记清除,以免造成内存泄漏。

优化循环

  1. 减值迭代
  2. 简化终止条件
  3. 简化循环体
  4. 使用后测试循环

减值迭代

日常应用不多,与增值迭代的区别,就在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];

其他

  1. 原生方法较快(Math)
  2. switch语句较快 (多个if情况下)
  3. 位运算符较快

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对象情况有:

  1. document.getElementByTagName()
  2. 获取元素的childNodes属性
  3. 获取元素的attributes属性
  4. document.forms,document.images

参考文档

作者:以乐之名

本文原创,有不当的地方欢迎指出。转载请指明出处。

读书笔记(03) - 性能 - JavaScript高级程序设计的更多相关文章

  1. 读书笔记(05) - 事件 - JavaScript高级程序设计

    HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...

  2. 读书笔记(02) - 可维护性 - JavaScript高级程序设计

    编写可维护性代码 可维护的代码遵循原则: 可理解性 (方便他人理解) 直观性 (一眼明了) 可适应性 (数据变化无需重写方法) 可扩展性 (应对未来需求扩展,要求较高) 可调试性 (错误处理方便定位) ...

  3. 读书笔记(01) - JSON - JavaScript高级程序设计

    JSON与JavaScript对象 JSON是一种表示结构化数据的存储格式,语法格式上与JavasScript对象有些类似. TIPS: 与JavaScript对象的格式区别 不支持变量.函数或对象实 ...

  4. 学习笔记:《JavaScript高级程序设计》

    第1章 JavaScript简介 1.一个完整的JavaScript实现应该由三部分组成:核心(ECMAScript),文档对象模型(DOM)和浏览器对象模型(BOM). 2.Web浏览器只是ECMA ...

  5. 《JavaScript高级程序设计》读书笔记--前言

    起因 web编程过程使用javascript时感觉很吃力,效率很低.根本原因在于对javascript整个知识体系不熟,看来需要找些书脑补一下,同时欢迎众网友监督. 大神推荐书籍 看了博客大神们推荐的 ...

  6. 《Javascript高级程序设计》读书笔记之对象创建

    <javascript高级程序设计>读过有两遍了,有些重要内容总是会忘记,写一下读书笔记备忘 创建对象 工厂模式 工厂模式优点:有了封装的概念,解决了创建多个相似对象的问题 缺点:没有解决 ...

  7. JavaScript高级程序设计(读书笔记)(一)

    本笔记汇总了作者认为“JavaScript高级程序设计”这本书的前七章知识重点,仅供参考. 第一章 JavaScript简介 JavaScript发展简史: 1995年,JavaScript诞生 19 ...

  8. 读书笔记(06) - 语法基础 - JavaScript高级程序设计

    写在开头 本篇是小红书笔记的第六篇,也许你会奇怪第六篇笔记才写语法基础,笔者是不是穿越了. 答案当然是没有,笔者在此分享自己的阅读心得,不少人翻书都是从头开始,结果永远就只在前几章. 对此,笔者换了随 ...

  9. (读书笔记)函数参数浅析-JavaScript高级程序设计(第3版)

    ECMAScript函数不介意传递的参数个数,因为在其内部是用一个数组进行表示的.在函数体内可以通过arguments对象来访问这个参数数组,就像我们正常访问数组一样处理. arguments对象只是 ...

随机推荐

  1. usb_ctrl

    IFCLK应该是clkout,与数据同步 flagd就是就是slcs FPGA的系统时钟用FX2LP的clkout时钟,个人觉得关键点在时钟是48M,别的异步时钟也是可以的. 模式配置 使用的模式是从 ...

  2. C#的委托与Java的自定义接口的异曲同工的同步操作

    C#的委托(以WinForm为例) 在子窗体(ChildFrm)中定义一个委托 this.CaptureListener(callback);//子窗体触发委托事件,以告诉调用的窗体 /// < ...

  3. poj 1094 Sorting It All Out 拓补排序

    Description An ascending sorted sequence of distinct values is one in which some form of a less-than ...

  4. 第一章javascript词法结构笔记摘要

    语法介绍 javascript最流行的脚本语言,用于web和HTML,服务器.pc.移动端 轻量级语言,可以插入HTML页面,由浏览器按编写顺序执行 一.字符集 用Unicode字符集编写,是ASCI ...

  5. http基本概念

  6. QT7有用的尝试总结(1)

    1,系统配置 1. 把系统相关的一些目录配置 写到qt.conf文件里,详细情况情参考QSettings里的qt.conf部分 You can use the qt.conf file to over ...

  7. CSS 基础 例子 背景色 & 背景图片

    背景简写形式 : body {background:#ffffff url('img_tree.png') no-repeat right top;} 一.背景色  background-color ...

  8. 背水一战 Windows 10 (42) - 控件(导航类): Frame 动画

    [源码下载] 背水一战 Windows 10 (42) - 控件(导航类): Frame 动画 作者:webabcd 介绍背水一战 Windows 10 之 控件(导航类) Frame 动画 示例An ...

  9. SVM的代码实现-python

    隔了好久木有更新了,因为发现自己numpy的很多操作都忘记了,加上最近有点忙... 接着上次 我们得到的迭代函数为 首先j != yi j = yi import numpy as np def sv ...

  10. javascript之快速排序

    快速排序思想其实还是挺简单的,分三步走: 1.在数组中找到基准点,其他数与之比较. 2.建立两个数组,小于基准点的数存储在左边数组,大于基准点的数存储在右边数组. 3.拼接数组,然后左边数组与右边数组 ...