本文翻译自 John Au-Yeung 的 JavaScript Best Practices — Performance,请参考原文阅读javascript
像任何其余编程语言同样,JavaScript 也有本身的最佳实践列表,以使程序更易于阅读和维护。JavaScript 有不少棘手的部分,所以应避免某些下降代码质量的作法。经过遵循最佳实践,咱们能够建立优雅且易于管理的代码,让任何人均可以轻松使用。java
在本文中,咱们将探讨提升应用程序性能的方法,包括将数据缓存在变量中,使用最快的方法循环遍历变量,减小 DOM 访问和页面上的元素,并推迟脚本加载。jquery
咱们应该减小访问应用程序中变量和对象属性的次数。git
这是由于每次执行此操做时,CPU 都必须一次又一次地访问内存中的项目以计算其结果。编程
所以,咱们应该尽量少地这样作。数组
例如,对于一个循环,不该像下面这样:promise
for(let i = 0; i < arr.length; i++) {
}
复制代码
而应该写成:浏览器
let length = arr.length;
for (let i = 0; i < length; i++) {
}
复制代码
这样,arr.length 在咱们的循环中仅被引用一次,而不是在每次迭代中都对其进行访问。缓存
在 JavaScript 中,有多种方法遍历可迭代对象。一种是老的 for 循环,其余方法包括 for...of 循环,数组的 forEach 方法。map 和 filter 操做也会遍历数组。还有 while 循环。bash
在运行循环的全部方式中,for 循环是最快的方式,不管是否像上面同样缓存 length,for 循环都是如此。可是,缓存 length 有时会使循环执行得更好。
一些浏览器引擎在不缓存 length 属性的状况下优化了 for 循环。
递减索引的 whil e循环比 for 循环慢大约 1.5 倍。
使用 forEach 循环的速度比 for 循环慢 10 倍,所以最好避免使用它,尤为是对于大型数组。
咱们能够在这里看到结果。
访问 DOM 是一项昂贵的操做,由于浏览器必须从网页中获取元素,而后从中建立一个对象并返回它。
为了减小 DOM 访问,若是咱们须要屡次操做 DOM Node 对象,则应该将其赋值给变量。
例如,若是咱们有如下 HTML,而且但愿在几秒钟后为其设置一些文本:
<p id='foo'>
</p>
复制代码
咱们能够编写如下代码来作到这一点:
const setText = (element, textContent) => {
return new Promise((resolve) => {
setTimeout(() => {
element.textContent = textContent;
resolve();
}, 3000)
})
}
(async () => {
const foo = document.querySelector('#foo');
await setText(foo, 'foo');
await setText(foo, 'bar');
await setText(foo, 'baz');
})();
复制代码
在上面的代码中,咱们有一个函数来获取咱们要操做的 HTML 元素以及要设置的文本内容。
setText 函数返回一个 promise,并将在 3 秒后将文本设置为给定元素。
而后咱们有一个 async 函数来设置文本 3 次。核心部分是咱们在每次调用时都将元素的引用传递给它。这样,咱们没必要每次从网页上获取元素,这是一项昂贵的操做。
DOM 树渲染起来很慢。所以,咱们必须减少树的大小。
这个别无选择,只能使咱们的网页尽量简单。
DOM 较小时,因为查找内容较少,所以可使用 querySelector,getElementById 或 getElementsByTagName 之类的方法更快地搜索元素。
此外,因为加载的内容更少,所以页面渲染性能也会提升。对于手机和平板电脑等速度较慢的设备尤为如此。
每次咱们声明变量时,浏览器都必须为变量分配存储空间。所以,为了减小内存使用,咱们不该该声明太多变量。
例如,若是咱们有如下 HTML:
<div id='foo'>
<p>
</p>
</div>
复制代码
咱们想设置 p 元素的文本内容,咱们不该该这样写:
const foo = document.querySelector('#foo');
const p = foo.querySelector('p');
p.textContent = 'foo';
复制代码
由于咱们这里有 2 个变量,这意味着咱们的计算机必须额外存储 2 个 JavaScript 变量的值。
咱们能够经过编写如下代码来减小变量声明:
document.querySelector('#foo p').textContent = 'foo';
复制代码
如咱们所见,咱们可使用 querySelector 方法经过 CSS 选择器选择任何内容。这意味着咱们应该使用此方法和相关的 querySelectorAll 方法来选择元素,由于它们均可以使用 CSS 选择器来选择任何 HTML 元素节点。
延迟脚本的加载 加载 JavaScript 文件是一项昂贵的操做。浏览器必须下载文件,解析内容,而后将其转换为机器代码并运行。
浏览器下载一个文件,同时会阻止其余任何操做。
所以,咱们应该尽量地延迟它。咱们能够经过将 script 标记放在末尾来实现。另外,咱们能够在 script 标签上使用 defer 属性来执行此操做。
另外,咱们能够在页面加载后经过动态建立 script 元素并按以下所示运行脚本:
window.onload = () => {
const element = document.createElement("script");
element.src = "https://code.jquery.com/jquery-1.12.4.min.js";
document.body.appendChild(element);
};
复制代码
页面加载后,想加载任何内容均可以使用此脚本的加载方法。
咱们能够经过作一些事情来加快页面速度。首先,咱们能够将数据缓存在变量中,所以咱们没必要重复访问它们。而后,咱们可使用 for 循环更快地遍历项目。
另外,咱们能够减少 DOM 大小以减小须要加载的项目。咱们还能够经过将 DOM 对象分配给变量来在其代码中缓存它们。
咱们也不该声明没必要要的变量,而且应尽量推迟脚本的加载,以避免卡住咱们的浏览器。