零、组织结构

根据引言,作者将全书划分为四个部分:

一、页面加载js的最佳方式(开发前准备)

二、改善js代码的编程技巧(开发中)

三、构建与部署(发布)

四、发布后性能检测与问题追踪(线上问题优化)

这样的组织结构也符合我们的开发习惯,首先进入第一部分。

一、JavaScript加载

起因:script脚本的加载会阻塞浏览器渲染页面和处理用户交互,如果加载的script脚本太多太大,就会长时间阻塞,造成页面假死。

解决方案:

1.脚本位置

放在底部。

放在底部可以保证页面主体结构已经基本加载完成展示给用户,才去加载script脚本。这条准则也有特例,如果是一些公司的埋点脚本,可能要求必须放在head里,以确保能上报页面加载时长。

2.组织脚本

减少script数量,合并脚本。

不论是使用concat打包工具合并,还是cdn提供的combo,都能达到该目的。

3.无阻塞脚本

在页面加载完成之后再去触发加载js,这样可以防止script加载阻塞页面。

原生defer

script标签自带defer属性,可以达到这个目的。捎带一提,async属性可以触发异步加载,合理利用了宽带。

动态脚本

或者使用动态脚本元素,通过js文件动态创建script标签,文件加载完成之后会立刻执行。

这个技术的重点在于不论在何时启动下载,文件的下载和执行过程都不会阻塞页面其他进程。

XMLHttpRequest脚本注入

通过XHR加载脚本,由于不是在script标签中加载,所以可以控制script标签中的代码执行时间。在需要的时候再去把script标签添加到页面上。

这也是jsonp的原理。

作者推荐的无阻塞模式

先加载很少量的jsLoader代码,之后通过loader来加载剩余的代码。

function loadScript(url, callback) {
var script = document.createElement('script');
script.type = 'text/javascript'; if (script.readyState) { // IE
script.onreadystatechange = function () {
if (script.readyState == 'loaded' || script.readyState == 'complete') {
script.onreadystatechange = null;
callback();
}
}
} else { // 其他浏览器
script.onload = function () {
callback();
}
} script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
} loadScript('rest.js', function () {
Rest.init()
});

YUI3、LazyLoad、LABjs

作者介绍了上述3个类库中lazyload的使用方式,其实原理就是上述所说,在体验上各有不同。关键就是loader中监听script的onload事件,决定script的执行时机。

二、高性能编程技巧

这个部分从2到8章分别介绍不同的提高性能的技巧。

1.数据存取

  • 数据的存取有四种方式,字面量、变量、数据项、对象。字面量和变量快于数组项和对象。

  • 局部变量位于作用域链的开始,查找速度最快,所处的位置越深,查找越慢,全局变量查找最慢。

  • with可以影响作用域链,try-catch语句中的catch也会影响。慎重使用。

  • 如果当前对象没有某个属性或者方法,就会去遍历原型链上的属性和方法,也会造成性能损耗。

  • 嵌套对象层数越多,也会减慢速度。例如,location.href要快于window.location.href。

  • 解决方法:

    大部分的性能损耗都是与对象查找相关,所以建议缓存对象,减少查找次数。

2.DOM编程

  • 由于DOM渲染引擎和JS引擎一般是分离实现的,要让两个相互独立的模块建立通讯,就会产生消耗。所以,我们需要减少DOM操作,已经获取的DOM节点,缓存下来,防止多次重复操作。

  • 其次,要注意重绘和重排,对DOM的哪些操作会引起重绘和重排,减少这方面的操作。

    最后,需要注意DOM事件处理用户交互。

  • 使用innerHTML和原生的document.createElement()类似的方法,速度相差不大。在最新版的webkit内核浏览器(chrome和safari)以外,innerHTML会更快,而且相较而言,代码量也少很多。

  • HTML集合是包含了DOM节点引用的类数组对象,例如document.getElementByName()这样的方法,需要注意的是HTML集合一直与文档保持着连接,每次需要新信息的时候,都会重新查询。

  • 在查找DOM元素时,尽可能使用原生方法,如最新支持比较完善的querySelectorAll()。

  • 在页面布局和几何属性改变时就需要“重排”,例如:

  1. 添加或者删除可见的DOM元素
  2. 元素位置改变
  3. 元素尺寸改变(包括:外边距、内边距、边框厚度、宽度、高度等属性改变)。
  4. 内容改变,例如:文本改变或者图片被另一个尺寸的图片替代
  5. 页面渲染器初始化
  6. 浏览器窗口尺寸改变
  • 为了减少重排和重绘,批量修改样式时,“离线”操作DOM树,使用缓存,并减少访问布局信息的次数。在动画中使用绝对定位,使用拖放代理。

  • 使用事件委托来减少事件处理器的数量。

3.算法和流程控制

  • 减少迭代的工作量,比如使用局部变量缓存数组的长度,减少查询次数。
  • 减少迭代次数,使用Duff's Device。
  • 尽可能不用forin,forin要比for、while、do-while要慢。
  • switch比if-else要快,但要综合考虑代码可读性。
  • 判断条件较多时,查找表要比if-else和switch更快。
  • 递归容易造成栈溢出,控制递归的循环次数。

4.字符串和正则表达式

  • 连接巨大的字符串时,数组项合并在IE7或更早之前版本是最优方法。
  • 如果在现代浏览器中,推荐使用简单的+和+=操作符代替,避免不必要的中间字符串。
  • 回溯是正则的基本组成,也会带来性能问题。
  • 回溯失控发生在正则表达式本应快速匹配的地方,因为某些特殊的字符串匹配动作导致运行缓慢甚至浏览器崩溃。为了避免这种情况,应该使相邻的字元互斥,避免嵌套量词对同一字符串的相同部分多次匹配,通过利用预查的原子组去除不必要的回溯。

5.快速响应的用户界面

  • 任何JavaScript任务不应该超过100ms,否则用户体验会变差。
  • JavaScript运行期间,浏览器响应用户交互的行为存在差异。
  • 定时器可用来安排代码延迟执行,但不一定绝对精确。
  • web worker允许程序员在UI线程外执行JavaScript代码,从而避免锁定UI。

6.AJAX

  • 减少请求数
  • 缩短页面加载时间,页面主要内容加载完成之后,用Ajax获取次要内容
  • 代码错误尽可能对用户屏蔽

7.最佳实践

  • 避免使用eval和Function构造器带来双重求值带来的性能损耗。
  • 使用直接量创建对象和数组,直接量更快
  • 避免重复工作,需要检测浏览器时,可使用延迟加载或者条件预加载。
  • 进行数学计算时,考虑使用位运算。
  • 尽量使用原生方法

三、构建与部署

  • 合并JavaScript文件以减少HTTP请求数
  • 使用YUI Compressor压缩JavaScript文件(事实上,如今nodejs下的打包工具更加好用)
  • 在服务端压缩JavaScript文件(Gzip编码)
  • 通过正确设置HTTP响应头来缓存JavaScript文件,通过向文件名加时间戳来避免缓存问题
  • 使用CDN

四、发布后性能检测与问题追踪

  • 使用网络分析工具找出加载脚本和页面中其他资源的瓶颈。
  • 把脚本延迟加载可以加快页面渲染速度,带来更好的用户体验
  • 使用性能分析工具找出脚本运行速度慢的地方,检查每个函数消耗的时间,以及函数被调用的次数,通过调用栈自身的一些线索来找出需要集中精力优化的地方

    一些工具:
  • YUI Profile
  • Firebug
  • Page Speed
  • Fiddler
  • YSlow
  • dynaTrace Ajax Edition

事实上,这些工具的功能在新版的chrome开发工具都有了,所以我建议好好学习chrome开发者工具。

感谢阅读。

高性能JavaScript读书笔记的更多相关文章

  1. 高性能javascript学习笔记系列(1) -js的加载和执行

    这篇笔记的内容主要涉及js的脚本位置,如何加载js脚本和脚本文件执行的问题,按照自己的理解结合高性能JavaScript整理出来的 javascript是解释性代码,解释性代码需要经历转化成计算机指令 ...

  2. 高性能javascript学习笔记系列(6) -ajax

    参考 高性能javascript javascript高级程序设计 ajax基础  ajax技术的核心是XMLHttpRequest对象(XHR),通过XHR我们就可以实现无需刷新页面就能从服务器端读 ...

  3. 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践

    参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...

  4. 高性能javascript学习笔记系列(4) -算法和流程控制

    参考高性能javascript for in 循环  使用它可以遍历对象的属性名,但是每次的操作都会搜索实例或者原型的属性 导致使用for in 进行遍历会产生更多的开销 书中提到不要使用for in ...

  5. 高性能javascript学习笔记系列(3) -DOM编程

    参考 高性能javascript 文档对象模型(DOM)是独立于语言的,用于操作XML和HTML文档的程序接口API,在浏览器中主要通过DOM提供的API与HTML进行交互,浏览器通常会把DOM和ja ...

  6. 高性能javascript学习笔记系列(2)-数据存取

    参考 高性能javascript Tom大叔深入理解javascript系列 相关概念 1.执行上下文   当控制器转到ecmascript可执行代码的时候,就会进入一个执行上下文,执行上下文是以堆栈 ...

  7. 数据结构与算法JavaScript 读书笔记

    由于自己在对数组操作这块比较薄弱,然后经高人指点,需要好好的攻读一下这本书籍,原本想这个书名就比较高深,这下不好玩了.不过看着看着突然觉得讲的东西都比较基础.不过很多东西,平时还是没有注意到,故写出读 ...

  8. 高性能的JavaScript -- 读书笔记

    高性能的JavaScript 一.      加载和运行 将脚本放在底部 脚本下载解析执行时,页面已经加载完成并显示在用户面前 成组脚本 减少外部脚本文件数量,整合成一个文件 延迟脚本 动态脚本元素 ...

  9. 你不知道的javascript读书笔记3

    概述 这是我看<你不知道的JavaScript(中卷)>中关于类型检查的笔记,供以后开发时参考,相信对其他人也有用. typeof 我们知道js中有七种内置类型:undefined, nu ...

随机推荐

  1. 捕获arm托管磁盘虚拟机,并进行还原

    背景:托管磁盘虚拟机"hlmma69n2",附加了一块100GB的数据磁盘.可以通过Portal管理界面直接捕获该虚拟机并进行还原,详情见如下步骤: 1.在虚拟机内部执行一般化的操 ...

  2. python_如何统计序列中元素

    问题1: 随机数列[12,5,8,7,8,9,4,8,5,...] 中出现次数最高的3个元素,他们出现的次数 问题2: 对某英文文章的单词,进行词频统计,找出出现次数最搞得10个单词,他们出现的次数是 ...

  3. 创建一个离线优先,数据驱动的渐进式 Web 应用程序

    原文地址:Build an offline-first, data-driven PWA 译文出自:我的个人博客 概述 在本文中,您将学习如何使用 Workbox 和 IndexedDB 创建离线优先 ...

  4. WebP 图片实践之路

    我们会从三部分来聊聊webp这个话题. 什么是webp,它有什么用? 使用webp的常规方法以及优劣. 我们是如何用上webp的. PS:如果是对webp有一定了解的朋友,建议直接看第三部分.因为是讲 ...

  5. vi使用手册

    VI是unix上最常用的文本编辑工具,我自己电脑上面也装了VIM编辑器,这个据称是程序员码字神器我实在没觉得那里舒服了,所以又用回了自己的Sublime.这里整理下vi常用操作,如果以后直接在Linu ...

  6. linkin大话设计模式--代理模式

    代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象的时候,客户端并不关心是否可以准确的得到这个对象,他只要一个能够提供该功能的对象而已,此时我们就可以返回该对象的代理.总而言之,客户端 ...

  7. Linux下安装mysql(yum和源码编译两种方式)

    这里介绍Linux下两种安装mysql的方式:yum安装和源码编译安装. 1. yum安装 (1)首先查看centos自带的mysql是否被安装: # yum list installed |grep ...

  8. PHPUnit使用教程——PHP环境变量+x-debug+composer+phpunit配置安装(超详细!)

    注意:Windows系统 一.提前入坑点:要求php5.6,7.0,7.1,不论使用集成版还是非集成版的小伙伴都要好好查看自己的php版本,个人的版本居然是5.5.X的,哭唧唧.不过别担心,爸爸教你升 ...

  9. Nginx+Keepalived负载均衡高可用

    Nginx+Keepalived负载均衡高可用方案: Nginx 使用平台:unix.linux.windows. 功能: A.www web服务  http 80 b.负载均衡(方向代理proxy) ...

  10. YII关联字段并带搜索排序功能

    1.简介 从接触yii框架到现在已经快有两个月了,但是自己对yii框架的了解程度并不是很深,并没有系统地去学习,仅仅只是在做项目的时候遇到不懂得知识才去翻手册. 在上一个项目中因为需要将关联的表的字段 ...