请说出 JavaScript无阻塞加载的具体方式?
参考回答
JavaScript 中实现无阻塞加载(Non-blocking Load)的方法主要有几种,它们可以让浏览器在加载 JavaScript 时不阻塞页面的渲染,从而提升用户体验。常见的无阻塞加载方式包括:
- 异步加载 (
async):通过async属性,脚本会异步加载并执行,不会阻塞 HTML 的解析。 - 延迟加载 (
defer):通过defer属性,脚本会在 HTML 完全解析后再执行,也不会阻塞页面的渲染。 - 动态脚本加载:通过 JavaScript 动态创建
<script>标签并插入到页面中,以实现异步加载脚本。 - 使用模块化加载(ES6 modules):ES6 模块(
<script type="module">)会默认异步加载。
详细讲解与拓展
- 使用
async属性async属性使得脚本异步加载。在脚本加载时,浏览器不会等待脚本加载完成,它会继续解析页面的其他部分。加载完成后,脚本会立即执行,执行时会暂停 HTML 的解析。这意味着,页面可能在脚本执行期间没有完全渲染,但这有助于提高加载速度。
例子:
<script src="example.js" async></script>- 特点:
- 脚本不会阻塞页面解析。
- 脚本加载完成后立即执行。
- 无法保证多个异步脚本的执行顺序,因此使用多个异步脚本时要小心依赖关系。
- 使用
defer属性defer属性使得脚本延迟执行,直到 HTML 文档完全解析并且 DOM 树构建完成之后才执行。这种方式也不会阻塞页面的解析,因此能有效提高页面渲染速度。
例子:
<script src="example.js" defer></script>- 特点:
- 脚本不会阻塞页面的解析。
- 保证所有使用
defer的脚本按顺序执行。 - 页面加载完成后,脚本按顺序执行。
- 动态脚本加载
- 通过 JavaScript 动态地创建
<script>标签并插入到 DOM 中,可以实现脚本的异步加载。动态加载的脚本与使用async或defer的<script>标签效果类似,但这种方式提供了更多的灵活性,可以在特定条件下加载脚本。
例子:
var script = document.createElement('script'); script.src = 'example.js'; script.async = true; // 可以选择是否设置 async 或 defer document.head.appendChild(script);- 特点:
- 可以在代码运行时动态决定是否加载某个脚本。
- 可选择是否异步加载(通过
async属性)或者延迟加载(通过defer属性)。
- 通过 JavaScript 动态地创建
- ES6 模块
- 在 HTML 中使用
<script type="module">标签时,默认启用了异步加载特性,脚本文件会异步加载并且按模块化的顺序执行。模块化的脚本可以导入和导出函数、对象等,并且默认是延迟执行的,直到 DOM 完全解析完毕。
例子:
<script type="module"> import {myFunction} from './example.js'; myFunction(); </script>- 特点:
- 默认异步加载和执行。
- 可以使用 ES6 的模块化功能(
import/export)。 - 脚本在加载后按顺序执行,确保模块间依赖关系。
- 在 HTML 中使用
总结
JavaScript 提供了几种方式来实现无阻塞加载:
– 使用 async 属性可以异步加载脚本,不会阻塞页面渲染,但执行顺序不可控。
– 使用 defer 属性则可以延迟脚本的执行,直到页面解析完成,且保证多个脚本按顺序执行。
– 动态创建 <script> 标签,可以灵活地控制脚本的加载时机。
– 使用 ES6 模块化脚本(type="module")默认异步加载,并且支持模块化的代码结构。
这些技术帮助提高页面的加载性能,确保 JavaScript 不会阻塞页面渲染,从而改善用户体验。