【JS】784- 14 个 JS 优化建议

JavaScript 已经成为当下最流行的编程语言之一。根据 W3Tech,全世界几乎 96% 的网站都在使用它。关于网站,你须要知道的最关键的一点是,你没法控制访问你网站的用户的硬件设备规格。访问你的网站的终端用户也许使用了高端或低端的设备,用着好的或差的网络链接。这意味着你必须确保你的网站是尽量优化的,你可以知足任何用户的要求。
javascript

这里有一些技巧,能够帮助你更好地优化 JavaScript 代码,从而提升性能。前端

顺便提一下,为了共享和复用 JS 组件,须要在高质量代码(须要花时间)和合理交付时间之间保持正确的平衡。你可使用流行的工具例如 Bit (Github),去共享组件(vanilla JS, TS, React, Vue 等)到 Bit 的 component hub,而不浪费太多时间。java

1. 删除不使用的代码和功能

程序包含越多的代码,给客户端传递的数据就越多。浏览器也须要更多的时间去解析和编译代码。webpack

有时,代码里也许会包含彻底未使用到的功能,最好只将这些额外的代码保留在开发环境中,而且不要把它们留到生产环境中,由于无用的代码可能会增长客户端浏览器的负担。c++

常常问本身那个函数、特性或代码是不是必需的。git

你能够手动的删掉无用的代码,也能够用工具 Uglify 或 谷歌开发的 Closure Compiler 帮你删。你甚至可使用一种叫作 tree shaking 的技术来删除程序中未使用的代码。例如打包工具 Webpack 就提供了它。你能够在 这里 了解更多关于 tree shaking 信息。还有,若是你想删掉未使用的 npm 包,你能够输入命令 npm prune 。阅读 NPM 文档 了解更多。github

2. 尽量缓存

缓存经过减小等待时间和网络请求提升了网站的速度和性能,所以减小了展现资源的时间。能够借助于 缓存 API 或 HTTP 缓存 实现它。你也许好奇当内容改变时发生了什么。上述缓存机制可以在知足某些条件(如发布新内容)时处理和从新生成缓存。web

3. 避免内存泄漏

做为一种高级语言,JS 负责几个低级别的管理,好比内存管理。对于大多数编程语言来讲,垃圾回收是一个常见的过程。通俗地说,垃圾回收就是简单地收集和释放,那些已经分配给对象,但目前又不被程序任一部分使用的内存。在像 C 这样的编程语言中,开发者必须使用 malloc()dealloc() 函数来处理内存分配和回收。算法

尽管垃圾回收是 JavaScript 自动执行的,但在某些状况下,它可能并不完美。在 JavaScript ES6 中,Map 和 Set 与它们的“weaker”兄弟元素一块儿被引入。“weaker”对应着 WeakMap 和 WeakSet,持有的是每一个键对象的“弱引用”。它们容许对未引用的值进行垃圾收集,从而防止内存泄漏。了解更多关于 WeakMaps 的信息。npm

4. 尽早跳出循环 Try to Break Out of Loops Early

执行循环在代码量大的循环中确定会消耗大量宝贵的时间,这就是为何要尽早打破循环的缘由。你可使用 break 关键字和continue 关键字跳出循环。编写最有效的代码是开发者们的责任。

在下面的例子中,若是你不在循环中使用 break ,你的代码将运行循环 1000000000 次,显然是超出负荷的。

let arr = new Array(1000000000).fill('----');
arr[970] = 'found';
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 'found') {
        console.log("Found");
        break;
    }
}

在下面的例子中,当不知足条件时若是你不使用 continue,那么将执行函数 1000000000 次。而咱们只处理了位于偶数位置的数组元素,就将循环执行减小了近一半。

let arr = new Array(1000000000).fill('----');
arr[970] = 'found';
for (let i = 0; i < arr.length; i++) {
  if(i%2!=0){
        continue;
    };
    process(arr[i]);
}

你能够在 这里 了解更多关于循环和性能。

5. 最小化变量的计算次数

要减小计算变量的次数,可使用闭包。JavaScript 中的闭包容许你从内部函数访问外部函数做用域。每次建立一个函数时都会建立闭包——但不调用。内部函数能够访问外部做用域的变量,即便外部函数已经调用结束。

让咱们看两个例子,看看这是怎么回事。这些例子的灵感来自 Bret 的博客。

function findCustomerCity(name{
  const texasCustomers = ['John''Ludwig''Kate']; 
  const californiaCustomers = ['Wade''Lucie','Kylie'];
  
  return texasCustomers.includes(name) ? 'Texas' : 
    californiaCustomers.includes(name) ? 'California' : 'Unknown';
};

若是咱们屡次调用上述函数,每次都会建立一个新对象。对于每一个调用,不会将内存从新分配给变量 texasCustometrscaliforniaCustomers

经过使用带有闭包的解决方案,咱们只能实例化变量一次。让咱们看看下面的例子。

function findCustomerCity({
  const texasCustomers = ['John''Ludwig''Kate']; 
  const californiaCustomers = ['Wade''Lucie','Kylie'];
  
  return name => texasCustomers.includes(name) ? 'Texas' : 
    californiaCustomers.includes(name) ? 'California' : 'Unknown';
};

let cityOfCustomer = findCustomerCity();

cityOfCustomer('John');//Texas
cityOfCustomer('Wade');//California
cityOfCustomer('Max');//Unknown

上述例子中,在闭包的帮助下,返回给变量 cityOfCustomer 的内部函数能够访问外部函数 findCustomerCity() 的常量。而且当调用内部函数并传参 name 时,不须要再次实例化这些常量。若是想要对闭包有更多了解,我建议你浏览Prashant的这篇博客。

6. 最小化 DOM 的访问

与其余 JavaScript 语句相比,访问 DOM 要慢一些。若是你要操做 DOM,从而触发重绘布局,那么操做会变得至关缓慢。

要减小访问 DOM 元素的次数,请访问它一次,并将其做为局部变量使用。当需求完成时,确保经过将变量设置为 null 来删除该变量的值。这将防止内存泄漏,由于它容许垃圾回收。

7. 压缩文件

经过使用诸如 Gzip 之类的压缩方法,能够减少 JavaScript 文件的大小。这些较小的文件将提高网站性能,由于浏览器只须要下载较小的资源。

这些压缩能够减小多达 80% 的文件大小。在这里了解更多关于 压缩:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer#text_compression_with_gzip


8. 缩小你的最终代码

有些人认为缩小和压缩是同样的。但却相反,它们是不一样的。在压缩中,使用特殊的算法来改变输出文件的大小。但在缩小中,须要删除 JavaScript 文件中的注释和额外的空格。这个过程能够在网上找到的许多工具和软件包的帮助下完成。缩小已经成为页面优化的标准实践和前端优化的主要组成部分。

缩小能够减小你的文件大小高达 60%。在这里了解更多关于 缩小。

9. 使用节流 throttle 和防抖 debounce

经过使用这两种技术,咱们能够严格执行代码须要处理事件的次数。

节流是指函数在指定时间内被调用的最大次数。例如,“最多每 1000 毫秒执行一次 onkeyup 事件函数”。这意味着若是你每秒输入 20 个键,该事件将每秒只触发一次。这将减小代码的加载。

另外一方面,防抖是指函数在上次触发后再次触发要间隔的最短期。换句话说,“仅当通过 600 毫秒而没有调用该函数时才执行该函数”。这将意味着,你的函数将不会被调用,直到 600 毫秒后,最后一次执行相同的函数。要了解更多关于节流和防抖的知识,这里有一个快速阅读。

你能够实现本身的防抖和节流函数,也能够从 Lodash 和 Underscore 等库导入它们。

10. 避免使用 delete 关键字

delete 关键字用于从对象中删除属性。关于这个 delete 关键字的性能,已经有一些争议。你能够在 此处 和 [此处](https://stackoverflow.com/questions/43594092/slow-delete-of-object- propertieses-in-js-in-v8/44008788) 中查看它们。这个问题有望在将来的更新中获得解决。

As an alternative, you can simply to set the unwanted property as undefined. 另外一种选择是,你能够直接将将不想要的属性设置为 undefined

const object = {name:"Jane Doe"age:43};
object.age = undefined;

你还可使用 Map 对象,由于根据 Bret,Map 的 delete 方法被认为更快。

11. 使用异步代码防止线程阻塞

你应该知道 JavaScript 是同步的,也是单线程的。可是在某些状况下,可能会花费大量的时间来执行一段代码。在本质上同步意味着,这段代码将阻止其余代码语句的运行,直到它完成执行,这会下降代码的总体性能。

但其实,咱们能够经过实现异步代码来避免这种状况。异步代码之前是以回调的形式编写的,可是在 ES6 中引入了一种处理异步代码的新风格。这种新风格被称为 promises。你能够在 MDN 的官方文档 中了解更多关于回调和 promises 的信息。

等等…

JavaScript默认是同步的,也是单线程的

为何在单一线程上运行,还能运行异步代码?这是不少人感到困惑的地方。这要归功于浏览器外壳下运行的 JavaScript 引擎。JavaScript 引擎是执行 JavaScript 代码的计算机程序或解释器。JavaScript 引擎能够用多种语言编写。例如,支持 Chrome 浏览器的 V8 引擎是用 c++ 编写的,而支持 Firefox 浏览器的 SpiderMonkey 引擎是用 C 和 c++ 编写的。

这些 JavaScript 引擎能够在后台处理任务。根据 Brian,调用栈识别 Web API 的函数,并将它们交给浏览器处理。一旦浏览器处理完成这些任务,它们将返回并做为回调推到堆栈上。

你有时可能想知道,Node.js 在没有浏览器帮助的状况下是如何运行的。事实上,为 Chrome 提供动力的 V8 引擎一样也为 Node.js 提供动力。下面是一篇由 Salil 撰写的很是棒的博客文章:Node.js真的是单线程吗,它解释了节点生态系统上的这个过程。

12. 使用代码分割

若是你有使用 Google Light House 的经验,你就会熟悉一个叫作“first contentful paint”的度量。它是 Lighthouse 报告的性能部分跟踪的六个指标之一。

First Contentful Paint(FCP)测量用户导航到页面后浏览器渲染 DOM 第一个内容所花费的时间。页面上的图像、非白色 <canvas> 元素和 SVG 被认为是 DOM 内容;iframe 中的任何内容都不被包含在内。

得到更高 FCP 分数的最好方法之一是使用代码分割。代码分割是一种在开始时只向用户发送必要模块的技术。减小最初传输的有效内容的大小,会显著地影响 FCP 得分。

流行的模块打包工具(如 webpack)提供了代码分割功能。你能够在原生 ES 模块的帮助下,加载各个模块。你能够阅读更多关于原生 ES 模块的 详细信息。

13. 使用异步 async 和延迟 defer

在现代网站中,脚本比 HTML 更密集,它们的尺寸更大,消耗更多的处理时间。默认状况下,浏览器必须等待脚本下载、执行,而后处理页面的其他部分。

庞大的脚本可能会阻塞网页的加载。为了不这种状况,JavaScript 提供了两种技术,即异步和延迟。你只需将这些属性添加到 <script> 标签。

异步是告诉浏览器在不影响页面渲染的状况下加载脚本。换句话说,页面不须要等待异步脚本,内容就会被处理和显示。

延迟是在呈现完成后告诉浏览器加载脚本的地方。若是你同时指定了二者,async 在现代浏览器中优先执行,而只支持 defer 但不支持 async 的旧浏览器将退回到 defer

这两个属性能够极大地帮助你减小页面加载时间。强烈建议你阅读一下 Flavio 的 JavaScript-async-defer。

14. 使用 Web Workers 在后台运行 CPU 密集型任务

Web Workers 容许在后台线程中运行脚本。若是你有一些高度密集的任务,你能够将任务分配给 web workers, web workers 将运行它们而不干扰用户界面。建立以后,web worker 能够经过向 JavaScript 代码指定的事件处理程序发送消息来与 JavaScript 代码通讯。反之亦然。

要了解更多关于 web workers 的信息,建议浏览 MDN 文档。


这篇文章就到这里,欢迎在评论中留言。

快乐编码!!


一些资源

  • Nodesource 的博客
  • Bret Cameron 的博客
  • 原文地址:14 JavaScript Code Optimization Tips for Front-End Developers
  • 原文做者:Mahdhi Rezvi
  • 译文出自:掘金翻译计划
  • 本文永久连接:https://github.com/xitu/gold-miner/blob/master/article/2020/14-javascript-code-optimization-tips-for-front-end-developers.md
  • 译者:Gesj-yean
  • 校对者:plusmultiply0, rachelcdev
 
    
    
     
     
              
     
 
    

1. JavaScript 重温系列(22篇全)
2. ECMAScript 重温系列(10篇全)
3. JavaScript设计模式 重温系列(9篇全)
4.  正则 / 框架 / 算法等 重温系列(16篇全)
5.  Webpack4 入门(上) ||  Webpack4 入门(下)
6.  MobX 入门(上)  ||   MobX 入门(下)
7. 8 0+篇原创系列汇总

回复“加群”与大佬们一块儿交流学习~

点击“阅读原文”查看 80+ 篇原创文章

本文分享自微信公众号 - 前端自习课(FE-study)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索