这本《高性能JavaScript》讲述了有关JavaScript性能优化的方方面面,主要围绕以下几个方面:

1> 加载顺序
2> 数据访问(如怎样的数据类型访问最快,怎样的作用域链最优)
3> DOM编程(如怎样的方式访问DOM元素性能是最优的)
4> 字符串和正则
5> Ajax
6> 编程实践(性能测试工具的使用、创建与部署JavaScript应用程序、如何提升程序响应)
var script = document.createElement ("script");
script.type = "text/javascript";
script.src = "file1.js";
document.getElementsByTagName_r("head")[0].appendChild(script);
  新的<script>元素加载file1.js源文件。此文件当元素添加到页面之后立刻开始下载。此技术的重点在于:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。你甚至可以将这些代码放在<head>部分而不会对其余部分的页面代码造成影响(除了用于下载文件的HTTP连接)。用XHR对象下载代码,并注入到页面中。(可以下载不立即执行的JavaScript代码)
var xhr = new XMLHttpRequest();
xhr.open("get", "file1.js", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
var script = document.createElement_x("script");
script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);

  ——推荐的非阻塞模式

推荐的向页面加载大量JavaScript的方法分为两个步骤:
  第一步,包含动态加载JavaScript所需的代码,然后加载页面初始化所需的除JavaScript之外的部分。这部分代码尽量小,可能只包含loadScript()函数,它下载和运行非常迅速,不会对页面造成很大干扰。当初始代码准备好之后,用它来加载其余的JavaScript。
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
//IE
if (script.readyState) {
script.onreadystatechange = function() {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
}
} else {
//非IE
script.onload = function() {
callback();
}
}
script.src = url;
document.getElementById("head").appendChild(script);
}
  第二步,应用loadScript函数在body的关闭标签之前的位置加载其余需要加载的JavaScript代码。

  第二章:数据访问

  在JavaScript中,数据存储位置可以对代码整体性能产生重要影响。有四种数据访问类型:直接量(字符串、数字、布尔值、对象、数组、函数、正则、null、undefined),变量(var局部变量),数组项(array[index]),对象成员(obj.propName | obj[‘propName’])。它们有不同的性能考虑。

  直接量和局部变量访问速度非常快,数组项和对象成员需要更长时间。

  局部变量比域外变量快,因为它位于作用域链的第一个对象中。变量在作用域链中的位置越深,访问所需的时间就越长。全局变量总是最慢的,因为它们总是位于作用域链的最后一环。

  避免使用with表达式,因为它改变了运行期上下文的作用域链。而且应当小心对待try-catch表达式的catch子句,因为它具有同样效果。

应用with包含的变量对象被插入到作用域链的前端,正因如此,访问激活对象被挤到了第二层,会导致访问局部变量的性能下降。故应避免。

  嵌套对象成员会造成重大性能影响,尽量少用。

由于对象成员可能包含其它成员,例如不太常见的写法window.location.href这种模式。每遇到一个点号,JavaScript引擎就要在对象成员上执行一次解析过程。成员嵌套越深,访问速度越慢。
一般来说,如果在同一个函数中你要多次读取同一个对象属性,最好将它存入一个局部变量。以局部变量替代属性,避免多余的属性查找带来性能开销。在处理嵌套对象成员时这点特别重要,它们会对运行速度产生难以置信的影响。

  一个属性或方法在原形链中的位置越深,访问它的速度就越慢。

  一般来说,你可以通过这种方法提高JavaScript代码的性能:将经常使用的对象成员,数组项,和域外变量存入局部变量中。然后,访问局部变量的速度会快于那些原始变量。

  第三章:DOM编程

  DOM访问和操作是现代网页应用中很重要的一部分。但每次你通过桥梁从ECMAScript岛到达DOM岛时,都会被收取“过桥费”。为减少DOM编程中的性能损失,请牢记以下几点:

  最小化DOM访问,在JavaScript端做尽可能多的事情。

  在反复访问的地方使用局部变量存放DOM引用。

 对于任何类型的DOM访问,如果同一个DOM属性或方法被访问一次以上,最好使用一个局部变量缓存该DOM成员。

  小心地处理HTML集合,因为他们表现出“存在性”,总是对底层文档重新查询。将集合的length属性缓存到一个变量中,在迭代中使用这个变量。如果经常操作这个集合,可以将集合拷贝到数组中。

当遍历一个集合时,第一个优化是将集合引用存储于局部变量,并在循环之外缓存length属性,然后, 如果在循环体中多次访问同一个集合元素,那么使用局部变量缓存它。

  注意重绘和重排版;批量修改风格,离线操作DOM树,缓存并减少对布局信息的访问。动画中使用绝对坐标。

1.重排版的情况列举:
    1>添加或删除可见的DOM元素
    2>元素位置改版
    3>元素尺寸改变(外边距、边框宽度、内边距、宽度、高度)
    4>内容改变(如,文本改变或图片被另一个不同尺寸的所替代)
    5>浏览器窗口改变尺寸(如出现滚动条)
  2.重排版和重绘代价昂贵,所以,提高程序响应速度一个好策略是减少此类操作发生的机会。3.为减少发生次数,你应该将多个DOM和风格改变合并到一个批次中一次性执行。
    1>当需要对DOM元素进行多次修改时,你可以通过以下步骤减少重绘和重排版的次数
      从文档流中摘除该元素
      (1)隐藏元素,进行修改,然后再显示它。
      (2)使用一个文档片段在已存DOM之外创建一个子树,然后将它拷贝到文档中。
      (3)将原始元素拷贝到一个脱离文档的节点中,修改副本,然后覆盖原始元素。
    2>对其应用多重改变
    3>将元素带回文档中
  4.对于处理具有动画效果的元素,需要将之脱离文档流

  使用事件托管技术最小化事件句柄数量。

  第四章:算法和流程控制

  正如其他编程语言,代码的写法和算法选用影响JavaScript的运行时间。与其他编程语言不同的是,JavaScript可用资源有限,所以优化技术更为重要。

 浏览器资源限制:
    1>调用栈尺寸限制
    2>长时间脚本限制(控制在100ms以内的响应算作好的用户体验)

  for,while,do-while循环的性能特性相似,谁也不比谁更快或更慢。

  除非你要迭代遍历一个属性未知的对象,否则不要使用for-in循环。

  改善循环性能的最好办法是减少每次迭代中的运算量,并减少循环迭代次数。

  运行的代码总量越大,使用这些策略所带来的性能提升就越明显。

  第五章:字符串和正则表达式

  密集的字符串操作和粗浅地编写正则表达式可能是主要性能障碍,但本章中的建议可帮助您避免常见缺陷。

  当连接数量巨大或尺寸巨大的字符串时,数组联合是IE7和它的早期版本上唯一具有合理性能的方法。

  如果你不关心IE7和它的早期版本,数组联合是连接字符串最慢的方法之一。使用简单的+和+=取而代之,可避免(产生)不必要的中间字符串。

  提高正则表达式效率的各种技术手段,帮助正则表达式更快地找到匹配,以及在非匹配位置上花费更少时间。

  正则表达式并不总是完成工作的最佳工具,尤其当你只是搜索一个文本字符串时。

虽然有很多方法来修整一个字符串,使用两个简单的正则表达式(一个用于去除头部空格,另一个用于去除尾部空格)提供了一个简洁、跨浏览器的方法,适用于不同内容和长度的字符串。从字符串末尾开始循环查找第一个非空格字符,或者在一个混合应用中将此技术与正则表达式结合起来,提供了一个很好的替代方案,它很少受到字符串整体长度的影响。

  第六章:响应接口

  JavaScript和用户界面更新在同一个进程内运行,同一时刻只有其中一个可以运行。这意味着当JavaScript代码正在运行时,用户界面不能响应输入,反之亦然。有效地管理UI线程就是要确保JavaScript不能运行太长时间,以免影响用户体验。最后,请牢记如下几点:

  JavaScript运行时间不应该超过100毫秒。过长的运行时间导致UI更新出现可察觉的延迟,从而对整体用户体验产生负面影响。

  JavaScript运行期间,浏览器响应用户交互的行为存在差异。无论如何,JavaScript长时间运行将导致用户体验混乱和脱节。

  定时器可用于安排代码推迟执行,它使得你可以将长运行脚本分解成一系列较小的任务。

  网页工人线程是新式浏览器才支持的特性,它允许你在UI线程之外运行JavaScript代码而避免锁定UI。

  网页应用程序越复杂,积极主动地管理UI线程就越显得重要。没有什么JavaScript代码可以重要到允许影响用户体验的程度。

  第七章:Ajax

  高性能Ajax包括:知道你项目的具体需求,选择正确的数据格式和与之相配的传输技术。

  作为数据格式,纯文本和HTML是高度限制的,但它们可节省客户端的CPU周期。XML被广泛应用普遍支持,但它非常冗长且解析缓慢。JSON是轻量级的,解析迅速(作为本地代码而不是字符串),交互性与XML相当。字符分隔的自定义格式非常轻量,在大量数据集解析时速度最快,但需要编写额外的程序在服务器端构造格式,并在客户端解析。

  当从页面域请求数据时,XHR提供最完善的控制和灵活性,尽管它将所有传入数据视为一个字符串,这有可能降低解析速度。另一方面,动态脚本标签插入技术允许跨域请求和本地运行JavaScript和JSON,虽然它的接口不够安全,而且不能读取信息头或响应报文代码。多部分XHR可减少请求的数量,可在一次响应中处理不同的文件类型,尽管它不能缓存收到的响应报文。当发送数据时,图像灯标是最简单和最有效的方法。XHR也可用POST方法发送大量数据。

  减少请求数量,可通过JavaScript和CSS文件打包,或者使用MXHR。

  缩短页面的加载时间,在页面其它内容加载之后,使用Ajax获取少量重要文件。

  Ajax是提升你网站潜在性能之最大的改进区域之一,因为很多网站大量使用异步请求,又因为它提供了许多不相关问题的解决方案,这些问题诸如,需要加载太多资源。对XHR的创造性应用是如此的与众不同,它不是呆滞不友好的界面,而是响应迅速且高效的代名词;它不会引起用户的憎恨,谁见了它都会爱上它。

  第八章:编程实践

  JavaScript提出了一些独特的性能挑战,关系到你组织代码的方法。网页应用变得越来越高级,包含的JavaScript代码越来越多,出现了一些模式和反模式。请牢记以下编程经验:

  通过避免使用eval_r()和Function()构造器避免二次评估。此外,给setTimeout()和setInterval()传递函数参数而不是字符串参数。

  创建新对象和数组时使用对象直接量和数组直接量。它们比非直接量形式创建和初始化更快。

  避免重复进行相同工作。当需要检测浏览器时,使用延迟加载或条件预加载。

//以前的方法
function addHandler(target, eventType, handler) {
if (target.addEventListener) {//DOM2 Events
target.addEventListener(eventType, handler, false);
} else {//IE
target.attachEvent("on" + eventType, handler);
}
}
function removeHandler(target, eventType, handler) {
if (target.removeEventListener) {//DOM2 Events
target.removeEventListener(eventType, handler, false);
} else {//IE
target.detachEvent("on" + eventType, handler);
}
}
//延迟加载
function addHandler(target, eventType, handler){
debugger;
//overwrite the existing function
if (target.addEventListener){ //DOM2 Events
addHandler = function(target, eventType, handler){
target.addEventListener(eventType, handler, false);
};
} else { //IE
addHandler = function(target, eventType, handler){
target.attachEvent("on" + eventType, handler);
};
}
//call the new function
addHandler(target, eventType, handler);
}
function removeHandler(target, eventType, handler){
//overwrite the existing function
if (target.removeEventListener){ //DOM2 Events
removeHandler = function(target, eventType, handler) {
target.addEventListener(eventType, handler, false);
}
} else { //IE
removeHandler = function(target, eventType, handler) {
target.detachEvent("on" + eventType, handler);
};
}
//call the new function
removeHandler(target, eventType, handler);
}
//条件预加载
var addHandler = document.body.addEventListener ? function(target, eventType, handler) {
target.addEventListener(eventType, handler, false);
} : function(target, eventType, handler) {
target.attachEvent("on" + eventType, handler);
};
var removeHandler = document.body.removeEventListener ? function(target, eventType, handler) {
target.removeEventListener(eventType, handler, false);
} : function(target, eventType, handler) {
target.detachEvent("on" + eventType, handler);
};

  当执行数学运算时,考虑使用位操作,它直接在数字底层进行操作,性能最优。

  原生方法总是比JavaScript写的东西要快。尽量使用原生方法。

  本书涵盖了很多技术和方法,如果将这些优化应用在那些经常运行的代码上,你将会看到巨大的性能提升。

  第九章:创建并部署高性能JavaScript应用程序

  开发和部署过程对基于JavaScript的应用程序可以产生巨大影响,最重要的几个步骤如下:

  合并JavaScript文件,减少HTTP请求的数量。

  使用YUI压缩器紧凑处理JavaScript文件。

  以压缩形式提供JavaScript文件(gzip编码)。

  通过设置HTTP响应报文头使JavaScript文件可缓存,通过向文件名附加时间戳解决缓存问题。

  使用内容传递网络(CDN)提供JavaScript文件,CDN不仅可以提高性能,它还可以为你管理压缩和缓存。

  所有这些步骤应当自动完成,不论是使用公开的开发工具诸如Apache Ant,还是使用自定义的开发工具以实现特定需求。如果你使这些开发工具为你服务,你可以极大改善那些大量使用JavaScript代码的网页应用或网站的性能。

  第十章:工具

  当网页或应用程序变慢时,分析网上传来的资源,分析脚本的运行性能,使你能够集中精力在那些需要努力优化的地方。

  使用网络分析器找出加载脚本和其它页面资源的瓶颈所在,这有助于决定哪些脚本需要延迟加载,或者进行进一步分析。

  传统的智慧告诉我们应尽量减少HTTP请求的数量,尽量延迟加载脚本以使页面渲染速度更快,向用户提供更好的整体体验。

  使用性能分析器找出脚本运行时速度慢的部分,检查每个函数所花费的时间,以及函数被调用的次数,通过调用栈自身提供的一些线索来找出哪些地方应当努力优化。

  虽然花费时间和调用次数通常是数据中最有价值的点,还是应当仔细察看函数的调用过程,可能发现其它优化方法。

  这些工具在那些现代代码所要运行的编程环境中不再神秘。在开始优化工作之前使用它们,确保开发时间用在解决问题的刀刃上。

  传个logo作纪念——

  

  原文英文及翻译:《高性能JavaScript》

												




											

【读书笔记】读《高性能JavaScript》的更多相关文章

  1. 读书笔记(高性能javascript)(一)

    1.加载与执行: (1)将脚本放在底部:(否则会阻塞) (2)由于每个<script>标签初始下载时都会阻塞页面渲染,所以减少页面包含的<script>标签数量有助于改善这一情 ...

  2. 读书笔记(高性能javascript)(二)

    5. 字符串和正则表达式: (1) 在大多数浏览器中,数组项合并(Array.prototype.join)比其他字符串连接方法更慢,但它却在IE7及更早版本浏览器中合并大量字符串唯一高效的途径: ( ...

  3. 【读书笔记--cookie】JavaScript权威指南 第六版

    遇到一些问题需要用cookie处理,正好读了一下犀牛书关于cookie的介绍,整理了一些笔记. cookie是指web浏览器存储的少量数据,同时它是与具体的web页面或者站点相关的. cookie数据 ...

  4. 【读书笔记】-- 你不知道的JavaScript

    <你不知道的JavaScript>是一个不错的JavaScript系列书,书名可能有些标题党的意思,但实符其名,很多地方会让你有耳目一新的感觉. 1.typeof null === &qu ...

  5. 读高性能JavaScript编程学英语 第一章第三页第一段话

    When the browser encounters a <script> tag, as in this HTML page, there is no way of knowing w ...

  6. javascript 数据结构和算法读书笔记 &gt; 第一章 javascript的编程环境和模型

    1.变量的声明和初始化 必须使用关键字 var,后跟变量名,后面还可以跟一个赋值表达式. var name; var age = 5; var str = 'hello'; var flg = fal ...

  7. 《JavaScript 高级程序设计》读书笔记二 使用JavaScript

    一   <script>元素 a.四个属性: async:立即异步加载外部脚本: defer:延迟到文档完全被解析再加载外部脚本: src:外部脚本路径: type:脚本语言的内容类型: ...

  8. 第四周读书笔记——读《我是一只IT小小鸟》有感

             读<我是一只IT小小鸟>有感 这是邓老师倾力推荐的一本书.这本书的标题化用了我们耳熟能详的歌词,算是较有新意吧.更重点在于,这本书的作者不是哪一位大牛,而是一群刚刚走出校 ...

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

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

  10. 读书笔记(03) - 性能 - JavaScript高级程序设计

    作用域链查找 作用域链的查找是逐层向上查找.查找的层次越多,速度越慢.随着硬件性能的提升和浏览器引擎的优化,这个慢我们基本可以忽略. 除了层级查找损耗的问题,变量的修改应只在局部环境进行,尽量避免在局 ...

随机推荐

  1. Bootstrap学习------按钮

    Bootstrap为我们提供了按钮组的样式,博主写了几个简单的例子,以后也许用的到. 效果如下 代码如下 <!DOCTYPE html> <html> <head> ...

  2. unity博文搜集

    一.综合篇 1. 脚本 unity3d脚本编程基础 2.Mecanim 使用Mecanim实现连击 3. 数学图形学 U3D需要用到的数学基础  2 4. shader 猫都能学会的Unity3D S ...

  3. [原创].NET 分布式架构开发实战五 Framework改进篇

    原文:[原创].NET 分布式架构开发实战五 Framework改进篇 .NET 分布式架构开发实战五 Framework改进篇 前言:本来打算这篇文章来写DAL的重构的,现在计划有点改变.之前的文章 ...

  4. Struts2漏洞解决

    如果你也正在使用Struts2作为web层框架做开发或者做公司的送检产品,然后被告知有各种各样的Struts2漏洞,那本篇博客值得你花时间来喽上一两眼. 前端时间抽空为公司做了新一代的送检产品,为了方 ...

  5. [BBS]搭建开源论坛之JForum富文本编辑器更换

    本文作者:sushengmiyan  本文地址:http://blog.csdn.net/sushengmiyan/article/details/47866905 上一节我们将开发环境搭建完成,我们 ...

  6. 通用Mapper环境下,mapper接口无法注入问题

    写了一个mapper接口 package com.nyist.mapper; import com.nyist.entity.User; import tk.mybatis.mapper.common ...

  7. SpringMVC @RequestParam和@RequestBody的区别

    问题:@Requestbody 用的时候遇到400和415错误,因为请求格式不对. @RequestBody @RequestBody能把简单json结构参数转换成实体类,如下代码: @Request ...

  8. 如何实现php手机短信验证功能

    http://www.qdexun.cn/jsp/news/shownews.do?method=GetqtnewsdetailAction&id=1677 下载php源代码 现在网站在建设网 ...

  9. c++之五谷杂粮---2

    2.1  我们通过调用运算符(call operator)来执行函数.调用运算符的形式是一对圆括号,它作用于一个表达式,该表达式是函数或者指向函数的指针:圆括号之内是用逗号隔开的实参列表,我们用实参初 ...

  10. mysql 数据库备份与还原,用户的创建与删除,用户的密码修改

    1.备份数据库 要退出mysql rimideiMac-23:~ rimi$    mysqldump -u root -p pro >pro.sql ls 查看路径 2.恢复数据库 2.1直接 ...