Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

高性能JavaScript笔记 #10

Open
yijinc opened this issue Jan 16, 2020 · 0 comments
Open

高性能JavaScript笔记 #10

yijinc opened this issue Jan 16, 2020 · 0 comments
Labels
blog blogs and articles

Comments

@yijinc
Copy link
Owner

yijinc commented Jan 16, 2020

JavaScript加载

  • 将所有 <script> 标签尽可能放置在页面的底部,紧靠 body 关闭标签 </body> 的上方,保证页面在脚本 运行之前完成解析样式
  • 将脚本成组打包 / 压缩。页面的 <script> 标签越少,页面的加载速度就越快,响应也更加迅速。(单个文件文件也不宜过大,可利用浏览器并行下载能力, 切割成多个文件)
  • 非阻塞方式下载 JavaScript:动态创建 <script> 元素;用 XHR 对象下载JavaScript代码,并注入到页面中
/***
* 推荐的非阻塞模式(用XHR下载JavaScript代码虽然不立即执行,可能存在跨域)
*/
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 { // Others
    script.onload = function () {
      callback();
    };
  }
  script.src = url;
  document.getElementsByTagName("head")[0].appendChild(script);
}

数据访问

  • 局部变量比域外变量快,因为它位于作用域链的第一个对象中。变量在作用域链中的位置越深,访问所需的时间就越长。全局变量总是最慢的,因为它们总是位于作用域链的最后一环。
  • 一个对象的属性或方法在原形链中的位置越深,访问它的速度就越慢,查找属性需要往原型链上遍历搜索,所以尽量使用直接量(简单类型)

DOM 编程

  • 最小化 DOM 访问,修改 DOM 元素会造成重绘和重新排版
  • 在ECMAScript处理数据,最后一次性调用dom操作
  • innerHTMLcreateElement / appendChild 性能比较:在老的浏览器 innerHTML 要快得多,在新的浏览器差距不大,甚至 createElement 表现更好
  • 遍历数组比遍历集合(HTML Collection 类数组)快,集合的 length 属性缓存到一个变量中,遍历集合时可先转化成数组副本
  • 遍历 children 比 childNodes 更快
  • 使用速度更快的 API,诸如 querySelectorAll()和 firstElementChild
    • offsetTop, offsetLeft, offsetWidth, offsetHeight
    • scrollTop, scrollLeft, scrollWidth, scrollHeight
    • clientTop, clientLeft, clientWidth, clientHeight
    • getComputedStyle() (currentStyle in IE)(在 IE 中此函数称为 currentStyle)
    获取布局信息这些属性和方法,需返回最新的数据,浏览器不得不刷新 渲染队列并重排版。所以 不要在布局信息改变时查询它
  • 页面中存在大量元素绑定了事件,使用事件托管

算法和流程控制

  • 优化循环工作量的第一步是减少对象成员和数组项查找的次数

  • 倒序循环是编程语言中常用的性能优化方法

  • forEach 比传统循环(for、while、do while)要慢,每个数组项要关联额外的函数 调用是造成速度慢的原因

  • 尽量减少循环中每次迭代的运算量,并减少循环迭代次数

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

  • switch 表达式总是比 if-else 更快,但只有当条件体数量很大时才明显更快。两者间的主要性能区别在于:当条件体增加时,if-else 性能负担增加的程度比 switch 更多

  • 将最常见的(频率高的)条件体放在 if-else 首位(更快作出选择)

  • 将 if-else 组织成一系列嵌套的 if-else 替换 else if 再判断,可以减少条件判断。

  • 当条件体的数目为大量离散值时,使用查表法(对象/数组/Map 直接选择)

  • 任何可以用递归实现的算法都可以用迭代实现。使用优化的循环替代长时间运行的递归函数可以提高性能, 因为运行一个循环比反复调用一个函数的开销要低。

  • 减少工作量就是最好的性能优化技术。代码所做的事情越少,它的运行速度就越快

  • 使用 memoization 技术,通过缓存先前计算结果为后续计算所重复使用,节省计算时间。

  • 算法本身复杂度优化

响应接口

  • 字符串合并:大多数情况下 String.prototype.concat 比简单的 + 和 += 慢

  • JavaScript 和UI界面在同一个主线程内运行,同一时刻只能其中一个可以运行。这意味着当 JavaScript 代码正在运行时,用户界面不能响应,反之亦然。

  • JavaScript 运行时间不应该超过 100 毫秒。过长的运行时间导致 UI 更新出现可察觉的延迟,从而对整体用户体验产生负面影响。这时可用定时器让出时间片,分解长运行脚本成为较短的片断

/**
 * 用定时器让出时间片, 每25ms后再将任务继续加入执行队列
 * 并且做了限时运行代码,在50ms内直接继续下一次的执行,(执行超过50ms后再让出时间片)
 * @param {array} items 需要处理的数组对象
 * @param {function} process 处理函数
 * @param {fucntion} callback 完成回调函数
*/
function timedProcessArray(items, process, callback) {
    var todo = items.concat(); //create a clone of the original
    setTimeout(function() {
        var start = +new Date();
        do {
            process(todo.shift());
        } while (todo.length > 0 && (+new Date() - start < 50));

        if (todo.length > 0) {
            setTimeout(arguments.callee, 25);
        } else {
            callback(items);
        }
    }, 25);
}

编程实践

  • eval,Function构造器,setTimeout 和 setInterval 允许在程序中运行包含代码的字符串,执行过程中会发生二次评估(二次评估是一项昂贵的操作),且可能是不安全的。所以,避免使用 eval 和 Function 构造器避免二次评估;给 setTimeout() 和 setInterval() 传递函数参数而不是字符串参数
  • 创建对象或数组使用直接量最快,占用较少空间
  • 不要做不必要的工作,不要重复做已经完成的工作
  • 延迟加载、条件预加载
  • 使用速度快的部分
  • 尽量使用原生方法

构建与部署

  • 预处理JavaScript文件:
  • 合并 JavaScript 文件,减少 HTTP 请求的数量
  • JavaScript Minification(紧凑): 剔除 js 文件中一切运行无关的内容,包括注释和不必要的空格
  • JavaScript Compression(压缩):携带 Accept-Encoding 的 HTTP 头(gzip 编码)
  • Caching JavaScript Files:使用 http缓存,通过向文件名附加时间戳或版本号解决缓存问题;使用 HTML 5 离线应用程序缓存
  • 使用内容传递网络(CDN)提供 JavaScript 文件,CDN 不仅可以提高性能,它还可以为你管理压缩和缓 存
@yijinc yijinc added the blog blogs and articles label Aug 20, 2021
@yijinc yijinc changed the title 高性能JavaScript 高性能JavaScript笔记 Jun 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog blogs and articles
Projects
None yet
Development

No branches or pull requests

1 participant