高性能的JavaScript

一、      加载和运行

  1. 将脚本放在底部

脚本下载解析执行时,页面已经加载完成并显示在用户面前

  1. 成组脚本

减少外部脚本文件数量,整合成一个文件

  1. 延迟脚本
  2. 动态脚本元素

非阻塞方式

  1. XMLHttpRequest

var xhr = new XMLHttpRequest();

xhr.open(“get”, “file.js", true);

xhr.onreadystatechange = function() {

if(xhr.readyState == 4) {

if ….

var script = document.createElement(“script”);

script.type = “text/javascript”;

script.text = xhr.responseText;

document.body.appendChild(script);

}

}

优点:可下载不立即执行的JavaScript代码

限制:JavaScript文件必须与页面放置在同一个域内

  1. 推荐的非阻塞模式

二、      数据访问

  1. 四种基本的数据访问方式:

直接量、变量、数组项、对象成员

  1. 管理作用域

每个JavaScript函数中都有一个仅供JavaScript引擎使用的内部属性为[[Scope]]。该属性包含了函数被创建的作用域链中对象的集合。

运行期上下文的作用域链中,一个标识符位置越深,它的读写速度就越慢。所以,函数中局部变量的访问速度总是最快的,而全局变量通常是最慢的。

  1. 改变作用域链

with表达式:作用域链前段插入了一个新的对象,局部变量的访问速度变慢。最好不要用。

try-catch表达式:catch子句执行完毕,作用域链返回原来的状态。

  1. 闭包,作用域,和内存

当闭包被运行时,一个运行期上下文将被创建,它的作用域链与[[Scope]]中引用的两个相同的作用域同时被初始化,然后一个新的激活对象为闭包自身被创建。

脚本中最好小心地使用闭包。

  1. 对象成员

对象成员比直接量和局部变量访问速度慢,在某些浏览器上比访问数组项还要慢。

所以可能的话避免使用它们,只在必要情况下使用对象成员。

  1. 总结:

提高性能:将经常使用的对象成员,数组项,和域外变量存入局部变量中。然后,访问局部变量的速度会快于那些原始变量。

三、      DOM编程

DOM操作代价昂贵

三类问题:

l  访问和修改DOM元素

l  修改DOM元素的样式,造成重绘和重新排版

l  通过DOM事件处理用户响应

  1. DOM访问和修改

轻轻地触摸DOM,并尽量保持在ECMAScript范围内。

不标准却被良好支持innerHTML和纯DOM方法如document.createElement()的性能差别不大。旧的浏览器上innerHTML快,新浏览器上DOM方法更快。

  1. 节点克隆

克隆节点更有效率,但提高不太多。

  1. HTML 集合对象

遍历数组比遍历集合快。

每次迭代过程访问集合length属性,性能低。应将length属性缓存到一个变量中,然后在循环判断条件中使用这个变量。

  1. 如果浏览器支持document.querySelectAll(),最好使用它
  2. 重绘和重排版

浏览器下载完所有页面HTML标记,JavaScript,CSS,图片后,它解析文件并创建两个内部数据

l  一棵DOM树:表示页面结构

l  一棵渲染树:表示DOM节点如何显示

当布局和几何改变时需要重排版:

l  添加或删除可见的DOM元素

l  元素位置改变

l  元素尺寸改变

l  内容改变

l  最初的页面渲染

l  浏览器窗口改变尺寸

  1. 最小化重绘和重排版

因为代价昂贵,所以好的策略是减少此类操作发生机会。将多个DOM和风格改变合并到一个批次中一次性执行。

l  隐藏元素,进行修改,然后再显示它。

display = none; 修改;display = block;

l  在已存DOM之外创建一个子树,然后拷贝到文档。

createDocumentFragment();append();

l  拷贝原始元素,修改副本,覆盖原始元素。

cloneNode();replaceChild();

第二种文档片段最优

  1. 缓冲布局信息
  2. 将元素提出动画流

使用以下步骤可以避免对大部分页面进行重排版

l  绝对坐标定位页面动画元素,使它位于页面布局流之外

尺寸改变时只会覆盖其他元素

l  启动元素动画

l  当动画结束时,重新定位,只一次下移文档其他元素位置

  1. 事件托管

事件逐层冒泡总被父元素捕获;

只需在一个包装元素上挂接一个句柄,用于处理子元素发生的所有事件;

DOM标准,每个事件有三个阶段:

捕获,到达目标,冒泡

10. 总结

为减少DOM编程中的性能损失,注意以下几点:

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

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

l  小心处理HTML集合,将length属性缓存到一个变量中

l  使用速度更快的API,如querySelectorAll()和firstElementChild

l  注意重绘和重排版;批量修改风格,离线操作DOM树,缓存并减少对布局信息的访问

l  动画中使用绝对坐标,使用拖放代理

l  使用时间托管技术最小化事件句柄数量

四、      算法和流程控制

代码整体结构是执行速度的决定因素之一

  1. 循环

for-in循环比其他普通循环明显要慢;

因为每次迭代操作要搜索实例或原形的属性。

减少迭代次数;

达夫设备:

var iterations = Math.floor(items.length/8);

startAt = items.length % 8;

i = 0;

do {

switch(startAt) {

case 0 : process(items[i++]);

case 7 : process(items[i++]);

case 6 : process(items[i++]);

case 5 : process(items[i++]);

case 4 : process(items[i++]);

case 3 : process(items[i++]);

case 2 : process(items[i++]);

case 1 : process(items[i++]);

}

startAt = 0;

} while(-- iterations);

  1. 基于函数的迭代

forEach()

比基于循环的迭代要慢:每个数组项要关联额外的函数调用;

关注执行时间的情况下它并不是一个合适的方法;

  1. 条件表达式

大多数情况下,switch比if-else更快,但只有当条件体数量很大时才明显;

两者区别:条件体增加时,if-else性能负担增加程度比switch多;

优化if-else:

条件体应当总是按照从最大概率到最小概率的顺序排列,保证理论运行速度更你快;

嵌套使用;

  1. 查表法

最常用于一个键和一个值形成逻辑映射领域

  1. 递归

递归函数会遇到浏览器调用栈大小的限制

五、      字符串和正则表达式

  1. 优化字符串连接

“+”,

“+=”,

Array.join(),

String.concat(),

str = str + “one” + “two”;

避免了使用临时字符串

  1. 数组联结
  2. 正则表达式优化

工作原理:

第一步:编译

第二步:设置起始位置

第三步:匹配每个正则表达式的字元

第四步:匹配成功或失败

六、      响应接口

  1. 浏览器UI线程

JavaScript和UI更新共享的进程被称为浏览器UI进程;

浏览器在JavaScript运行时间上采取了限制:

调用栈尺寸限制和长时间脚本限制;

  1. 用定时器让出时间片

setTimeout()和setInterval()

第二个参数指出是么时候应当将任务添加到UI队列之中,并不是说那时代码被执行;

  1. 分解任务
  2. 限时运行代码
  3. Web Work

不绑定UI线程,不能访问许多浏览器资源。

七、Ajax异步JavaScript和XML

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

  1. 《高性能MySQL》读书笔记--锁、事务、隔离级别 转

    1.锁 为什么需要锁?因为数据库要解决并发控制问题.在同一时刻,可能会有多个客户端对表中同一行记录进行操作,比如有的在读取该行数据,其他的尝试去删除它.为了保证数据的一致性,数据库就要对这种并发操作进 ...

  2. 【高性能Mysql 】读书笔记(三)

    第5章 创建高性能的索引 本文为<高性能Mysql 第三版>第四章读书笔记,Mysql版本为5.5 索引基础 索引的重要性:找一本800面的书的某一段内容,没有目录也没有页码(页码也可类比 ...

  3. 【高性能Mysql 】读书笔记(二)

    第4章 Schema 与数据类型优化 本文为<高性能Mysql 第三版>第四章读书笔记,Mysql版本为5.5 选择优化的数据类型 选择合适数据类型的三个原则 更小的通常更好 - 速度更快 ...

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

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

  5. 高性能JavaScript读书笔记

    零.组织结构 根据引言,作者将全书划分为四个部分: 一.页面加载js的最佳方式(开发前准备) 二.改善js代码的编程技巧(开发中) 三.构建与部署(发布) 四.发布后性能检测与问题追踪(线上问题优化) ...

  6. 《高性能js》读书笔记

    第一章:加载和执行 .浏览器的JavaScript的引擎是编译器层的优化: .当浏览器执行JavaScript代码时,不能同时做其他任何事情(单一进程),意味着 .主流浏览器都允许并行下载JS. .减 ...

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

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

  8. JavaScript读书笔记(1)

    从今天开启每天看书记笔记模式,<JavaScript高级程序设计(第3版)> 1. Javascript最初是为了解决输入验证器的问题,现在已经发展成一门复杂的语言: 2.  语言标准为E ...

  9. JavaScript读书笔记(一)

    自动类型转换 在JavaScript中,使用 == .=== 和 - 等运算符能够使得类型自动转换. 关于不同类型的值的比较 flase == 0; //true "" == fl ...

随机推荐

  1. Android View绘制13问13答

    1.View的绘制流程分几步,从哪开始?哪个过程结束以后能看到view? 答:从ViewRoot的performTraversals开始,经过measure,layout,draw 三个流程.draw ...

  2. 使用服务器端控制AJAX页面缓存

    你知道 response.setHeader("Cache-Control","no-cache"); 这条语句是干什么的吗? 这是用来防止浏览器缓存动态内容生 ...

  3. iOS 开发者必不可少的 75 个工具,你都会了吗

    如果你去到一位熟练的木匠的工作室,你总是能发现他/她有一堆工具来完成不同的任务. 软件开发同样如此.你可以从软件开发者如何使用工具中看出他水准如何.有经验的开发者精于使用工具.对你目前所使用的工具不断 ...

  4. XX.frame.origin.x 赋值问题

    can't use that myView.frame.origin.x=25.0; 因为.操作 和 = 一起用的话会调用 set方法.所以上式是行不通的. 可以用下面的方式来实现. that I h ...

  5. 理解javascript的caller,callee,call,apply概念

    在提到上述的概念之前,首先想说说javascript中函数的隐含参数:arguments Arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]arguments[ ...

  6. Tomcat: localhost:8080 提示404

    下午配置环境,配置完成后,欣喜地进入localhost:8080,结果给我提示404 心想:尼玛,这localhost都还会404,这不坑爹吗?! 琢磨了好久,结果被我搞定了,只需要做一个改动: 打开 ...

  7. 利用DescriptionAttribute定义枚举值的描述信息 z

    System.ComponentModel命名空间下有个名为DescriptionAttribute的类用于指定属性或事件的说明,我所调用的枚举值描述信息就是DescriptionAttribute类 ...

  8. JAVA多线程二

    Thread.Join() join()函数表示等待当前线程结束,然后返回. public final synchronized void join(long millis) throws Inter ...

  9. jQuery需要掌握的技巧

    检查 jQuery 是否加载 在使用 jQuery 进行任何操作之前,你需要先确认它已经加载: if (typeof jQuery == 'undefined') { console.log('jQu ...

  10. EFSQLserver

    1.增加一条烽据 FLYNEWQKEntities dataContext = new FLYNEWQKEntities(); Log log = new Log(); log.Data1 = &qu ...