script标签以及defer和async属性

2024-05-16 00:20
文章标签 script 属性 标签 async defer

本文主要是介绍script标签以及defer和async属性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. <script>标签

将JavaScript代码嵌入到HTML中主要方式是使用<script>元素。
使用<script>的方式有两种:
(1)直接在网页中嵌入JavaScript代码:

<script>function sayHi() {console.log("Hi");}
</script>

包含在<script>中的代码会被从上到下执行,在<script>元素中的代码被计算完成之前,页面的其余内容不会被加载也不会被显示。

(2)引入外部文件中的代码,使用src属性,该属性的值是一个URL,指向包含js代码的文件。

<script src="example.js"></script>

与解释行内的js代码一样,在解释外部的js文件时,页面也会阻塞,阻塞的时间也包含下载文件的时间(不使用defer和async的情况下)。

如果使用了src属性,就不应该在<script></script>之间再包含其他js代码。如果两者都提供的话,则浏览器只会下载并执行脚本文件,从而忽略行内代码。

在没有使用deferasync属性时,浏览器会按照<script>在页面中出现的顺序依次解释它们。第二个<script>元素的代码必须在第一个<script>元素的代码解释完毕才能开始解释,依次类推。

2. <script>标签位置

浏览器的渲染引擎与js引擎是互斥的,当HTML解析器遇到一个script标签时,它就会暂停渲染过程,将控制权交给js引擎。js引擎对内联的js代码会直接执行,对外部的js文件要先获取,再执行。等js引擎运行完毕,浏览器又会把控制权还给渲染引擎,继续DOM和CSSOM的构建。

过去,所有的script标签都被放在页面的<head>标签内,如下:

<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script src="example1.js"></script><script src="example2.js"></script>
</head>

这种做法的主要目的是将外部CSS和JavaScript文件集中在一起。然后所有的JS文件都放在<head>内,意味着所有的JavaScript代码都下载、解析和解释完毕后,才能开始渲染页面(页面在浏览器解析到<body>的起始标签时开始渲染)。如果引入的脚本过多,会导致页面的渲染明显延迟,浏览器窗口完全空白。
为了解决这个问题,现在通常将所有JavaScript的引用放在<body>元素中的页面内容后面:

  <body>......<script src="example1.js"></script><script src="example2.js"></script></body>

这样会在处理js代码之前完全的渲染页面,用户会感觉页面加载更快了。

image.png

image.png

可以发现,没有加defer和async属性的脚本,在遇到<script>标签时,首先开始下载脚本,从脚本开始下载到脚本完成执行,整个过程中,HTML的解析都是停止的。当脚本解析完成后,HTML解析继续。

3. <script>标签的defer属性

defer属性只对外部的脚本文件有效,给<script>标签添加defer属性,可以推迟脚本的执行。在遇到脚本时,还是会立即下载,但是会延迟执行。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><script src="./scripts/a.js" defer></script></head><body><ul><li>HTML</li><li>CSS</li><li>JAVASCRIPT</li></ul></body>
</html>

上面的<script>标签虽然包含在<head>中,由于加上了defer属性,它们会在浏览器解析到结束的</html>标签后才会执行。
HTML5规范要求脚本应该按照它们出现的顺序执行,因此第一个推迟的脚本会在第二个推迟的脚本之前执行,而且两者都会在DOMContentLoaded事件之前执行。但是在实际情况下,推迟执行的脚本不一定总会按顺序执行,或者在DOMContentLoaded事件之前执行。因此最好只包含一个这样的脚本。

image.png

可以发现,对于defer的脚本,脚本下载时,HTML仍然在解析,当HTML解析完成以后,开始执行脚本,即延迟执行。

4. <script>标签的async属性

async属性也只适用于外部脚本,浏览器同样会立即下载脚本,但是与defer不同的是,async的脚本不能保证按照它们出现的次序执行,而且当该脚本下载完成后就会立即执行该脚本。由于脚本大小不一样,下载完成的所需要的时间不同,所以这些脚本不能保证按照出现顺序执行。

image.png

可以发现,对于async的脚本,脚本下载时,HTML仍然在解析,但是与defer不同的是,当脚本下载完成后立即就会执行脚本。

脚本下载可能很快,此时HTML还没有完成解析(DOMContentLoaded事件还没触发),首先暂停HTML解析,去执行脚本,之后继续解析。
脚本下载也可能较慢,此时HTML解析已经完成了(DOMContentLoaded事件已经触发了),直接执行脚本。

async属性的脚本会保证在页面的load事件之前执行,但是可能在DOMContentLoaded事件之前或者之后执行,由于无法确定该脚本执行时机,异步脚本不应该在加载期间操作DOM。

5. 如何使用
  1. 如果脚本是一个模块并且不依赖于其他任何脚本,则使用async
  2. 如果脚本依赖于其他脚本或者被其他脚本依赖,则使用defer
  3. 如果该脚本很小并且被一个async的脚本依赖,则使用内联的脚本,并且把该脚本放在async脚本的上面。

参考[async vs defer attributes](async vs defer attributes - Growing with the Web)
js高程四

这篇关于script标签以及defer和async属性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/993340

相关文章

SpringBoot读取ZooKeeper(ZK)属性的方法实现

《SpringBoot读取ZooKeeper(ZK)属性的方法实现》本文主要介绍了SpringBoot读取ZooKeeper(ZK)属性的方法实现,强调使用@ConfigurationProperti... 目录1. 在配置文件中定义 ZK 属性application.propertiesapplicati

Java反射实现多属性去重与分组功能

《Java反射实现多属性去重与分组功能》在Java开发中,​​List是一种非常常用的数据结构,通常我们会遇到这样的问题:如何处理​​List​​​中的相同字段?无论是去重还是分组,合理的操作可以提高... 目录一、开发环境与基础组件准备1.环境配置:2. 代码结构说明:二、基础反射工具:BeanUtils

MySQL 事务的概念及ACID属性和使用详解

《MySQL事务的概念及ACID属性和使用详解》MySQL通过多线程实现存储工作,因此在并发访问场景中,事务确保了数据操作的一致性和可靠性,下面通过本文给大家介绍MySQL事务的概念及ACID属性和... 目录一、什么是事务二、事务的属性及使用2.1 事务的 ACID 属性2.2 为什么存在事务2.3 事务

javascript fetch 用法讲解

《javascriptfetch用法讲解》fetch是一个现代化的JavaScriptAPI,用于发送网络请求并获取资源,它是浏览器提供的全局方法,可以替代传统的XMLHttpRequest,这篇... 目录1. 基本语法1.1 语法1.2 示例:简单 GET 请求2. Response 对象3. 配置请求

使用Python和Tkinter实现html标签去除工具

《使用Python和Tkinter实现html标签去除工具》本文介绍用Python和Tkinter开发的HTML标签去除工具,支持去除HTML标签、转义实体并输出纯文本,提供图形界面操作及复制功能,需... 目录html 标签去除工具功能介绍创作过程1. 技术选型2. 核心实现逻辑3. 用户体验增强如何运行

JavaScript实战:智能密码生成器开发指南

本文通过JavaScript实战开发智能密码生成器,详解如何运用crypto.getRandomValues实现加密级随机密码生成,包含多字符组合、安全强度可视化、易混淆字符排除等企业级功能。学习密码强度检测算法与信息熵计算原理,获取可直接嵌入项目的完整代码,提升Web应用的安全开发能力 目录

Spring Cache注解@Cacheable的九个属性详解

《SpringCache注解@Cacheable的九个属性详解》在@Cacheable注解的使用中,共有9个属性供我们来使用,这9个属性分别是:value、cacheNames、key、key... 目录1.value/cacheNames 属性2.key属性3.keyGeneratjavascriptor

Spring Boot 事务详解(事务传播行为、事务属性)

《SpringBoot事务详解(事务传播行为、事务属性)》SpringBoot提供了强大的事务管理功能,通过@Transactional注解可以方便地配置事务的传播行为和属性,本文将详细介绍Spr... 目录Spring Boot 事务详解引言声明式事务管理示例编程式事务管理示例事务传播行为1. REQUI

JavaScript时间戳与时间的转化常用方法

《JavaScript时间戳与时间的转化常用方法》在JavaScript中,时间戳(Timestamp)通常指Unix时间戳,即从1970年1月1日00:00:00UTC到某个时间点经过的毫秒数,下面... 目录1. 获取当前时间戳2. 时间戳 → 时间对象3. 时间戳php → 格式化字符串4. 时间字符

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程