• 高性能的JavaScript -- 读书笔记


    高性能的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

  • 相关阅读:
    mysql 安装及基本点
    logback中的additivity属性
    chrome中,拖动.crx无响应
    Java安装
    mysql多表连接的几种写法
    Ionic -- Refresher & InfiniteScroll 下拉刷新与滚动懒加载
    ng-cli + ionic-cli 常用命令
    Vue笔记(五):Vuex
    JavaScript设计模式(三):发布—订阅模式(观察者模式)
    Windows下解决项目未正确关闭引起的nodejs端口占用
  • 原文地址:https://www.cnblogs.com/dreamerjdw/p/5945738.html
Copyright © 2020-2023  润新知