Script标签和脚本执行顺序

一文大白话讲清楚script加载和执行顺序,包括script标签、defer、async、动态script等 本文详细分析了script标签的加载和执行顺序,包括普通script标签、defer、async和动态script四种方式。普通script会阻塞HTML解析,按顺序执行;defer异步加载但保持顺序执行,在DOMContentLoaded前完成;async异步加载且立即执行,不保证顺序;动态script默认类似async,但设置async=false后可保证顺序执行。每种方式适用于不同场景,开发者应根据需求选择合适的方法来优化页面加载性能。 阅读详情

0.前言

估计所有读者也慢慢适应我每次讲东西之前先墨迹一段的习惯了。

那么我今天就来个转换,我!不!墨!迹!了!

正文开始。

1.script标签的默认行为


首先我们先来看一下 <script> 标签 的几个重要特性:

  • script标签的会阻止文档渲染。相关脚本会立即下载并执行。
    注意:(不带defer或async属性)
  • document.currentScript 可以获得当前正在运行的脚本(Chrome 29+, FF4+)。
  • 脚本顺序再默认情况下和script标签出现的顺序一致。

既然我们已经明确了 script 标签的基本特性。

那我们就先来看一个例子,用这个例子来说明 script 的加载顺序问题。

2. script 的加载顺序


假设如下简单代码,我们去看一下,执行的结果是什么样子?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李鹏:3206064928</title>
</head>
<body>

</body>
    <script>alert("MR_LP : A");</script>
    <script>alert("MR_LP : B");</script>
    <script>alert("MR_LP : C");</script>
</html>

执行结果如下:

这是我们按照正常的逻辑去执行,分别弹出了 :

  1. MR_LP : A
  2. MR_LP : B
  3. MR_LP : C

那我们再去考虑一下,在有网络的情况,请求的顺序会怎样呢?

在这里我去做一个限制,将我们的第二个文件中,书写非常多的注释,让我们的第二个文件大小要远远大于另外两个文件。

这时候我们再去看一下,顺序是什么样子的。

结果如何呢?

你会发现我们的加载顺序和上面一模一样。

这是为什么呢?第二个文件明明要大于另外两个文件呀。

这里就要说到 script标签 的柱塞式执行方式了。

3. script 标签的属性


在说上面的问题之前,咱们先回顾一下,script 标签 的六个属性。

属性名介绍
1type
2src
3charset
4language
5async
6defer

注意:
虽然text/javascript 和text/ecmascript 都已经不被推荐使用,
但人们一直以来使用的都还是text/javascript。
实际上,服务端在传送JavaScript 文件时使用的 MIME 类型通常是application/x-javascript,
但在type中设置这个值却可能导致脚本被忽略。
另外,在非IE浏览器中
还可以使用以下值:application/javascript 和application/ecmascript。
考虑到约定成俗和最大限度的浏览器兼容性,
目前type 属性的值依旧还是text/javascript。

除此之外,属性 1 ~ 4 是 HTML4.01中定义的,而 5 和 6 则是 HTML 5 中新增的内容,那我们接下来就专门针对这两个新属性,来看一下,script 的柱塞式执行。

4.async属性


async属性是HTML5的新特性,这意味着其兼容性并不乐观(IE10+)。

async表示该script标签并不柱塞,也不同步执行。

浏览器只需要在脚本下载完毕后再执行即可——不必柱塞页面渲染等待该脚本的下载和执行。

如下代码[^4],会得到三个alert,但是alert的内容分别是”A”,”C”,”B”。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李鹏:3206064928</title>
</head>
<body></body>
<script  src="https://snipt.net/raw/7b08744009c450e07c0bfc1d606fc72e/"></script>
<script  src="https://snipt.net/raw/a2e8c05c1f6fc0e47d259aa899304e89/" async="async"></script>
<script  src="https://snipt.net/raw/4fab3017d3d46cbfc4bbd88aab006650/"></script>
</html>

运行结果如下:

可以看到,第二个script标签在加入async后,并没有阻止后续文档解析和脚本执行。

考究这个属性产生的原有,其实有大量的脚本加载器在做这样的事情:

var script = document.createElement("script");
script.src = "file.js";
document.body.appendChild(script);

那么我们不难想象,通过脚本异步插入的script标签达到的效果和带async属性的script标签是一样的。

换句话说,由脚本插入的script标签默认是async的。

另外,对內联脚本设置async属性是没有意义的,也不产生其他效果。

其包含的脚本总是立即执行的。

5. defer属性


带有defer属性的脚本,同样会推迟脚本的执行,并且不会阻止文档解析。

就如同这个脚本,放置到了文档的末尾(</body>之前)。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李鹏:3206064928</title>
</head>
<body></body>
<script  src="https://snipt.net/raw/7b08744009c450e07c0bfc1d606fc72e/"></script>
<script  src="https://snipt.net/raw/a2e8c05c1f6fc0e47d259aa899304e89/" defer="defer"></script>
<script  src="https://snipt.net/raw/4fab3017d3d46cbfc4bbd88aab006650/"></script>
</html>

上面的代码的宏观现象和加了async属性的例子是一样的,都是会得到”A”、”C”、”B”的三个alert。

但是其原理是不一样的。

defer属性是会确保脚本在文档解析完毕后执行的。

即使这个脚本在文档解析过程中就已经下载完毕变成可执行的状态,

浏览器也会推迟这个脚本的执行,直到文档解析完毕,并在DOMContentLoaded之前。

同时,带有defer的脚本彼此之间,能保证其执行顺序。

注意,defer属性并不是每个浏览器支持,

即便支持的浏览器,也会因为版本不一样导致具体行为不一致。

另外,大家可以通过将script标签放置到文档末尾这种简单的做法达到defer属性一样的效果。

defer属性早在IE4就被支持,但是这个defer属性和现代浏览器的行为是有区别的。

只有IE10以上,才开始按照标准执行defer属性。

6. async与defer的影响


参考W3C的官方文档,defer和async两个属性是可以互相影响的:

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.

简单的归纳:

  • 仅有async属性,脚本会异步执行
  • 仅有defer属性,脚本会在文档解析完毕后执行
  • 两个属性都没有,脚本会被同步下载并执行,期间会柱塞文档解析

规范里没有提到两种属性都有时的效果,但这是文档中被允许的。

这样的具体效果会在后面讨论。

7. document.write的影响

docuemnt.write允许向打开的文档流中写入文档内容;

内嵌到HTML里面的docuemnt.write可以就地添加文档内容。

考虑到docuemnt.write写入script标签的情况:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李鹏:3206064928</title>
</head>
<body></body>
<script  src="https://snipt.net/raw/7b08744009c450e07c0bfc1d606fc72e/"></script>
<script>document.write("\<script  src=https://snipt.net/raw/a2e8c05c1f6fc0e47d259aa899304e89 \/\>\<\/script\>");</script>
<script  src="https://snipt.net/raw/4fab3017d3d46cbfc4bbd88aab006650/"></script>
</html>

执行结果如下:

我们观察到执行顺序和普通的script标签没有区别。

即使你插入的标签带有async或defer,其行为也是没有区别的。

让人纠结的是反过来使用。

将我们的 document.write 写在页面中时,其余加载按照正常顺序。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>李鹏:3206064928</title>
</head>
<body></body>
<script src="https://snipt.net/raw/7b08744009c450e07c0bfc1d606fc72e/"></script>
<script src="https://snipt.net/raw/773d794c9051a238e5c102e65dbaa2e9/"></script>
<script src="https://snipt.net/raw/4fab3017d3d46cbfc4bbd88aab006650/"></script>
</html>

加载结果如下:

由于第二个脚本是通过document.write写入的。

被延迟的脚本在执行时,document已经关闭,document.write是没有任何效果的。

所以,不管使用defer还是async,第二个脚本始终没有运行。


本文参考于 《JS 编程指南》

script标签的defer和async属性的使用 defer属性用于延迟脚本的执行,脚本会按照它们在页面中出现的顺序依次执行,而不阻塞页面的解析和渲染过程。async属性用于异步加载和执行脚本,脚本会在加载完成后立即执行,不需要等待页面解析完毕,但脚本的执行顺序是不确定的。当浏览器遇到带有defer属性的script标签时,它会继续解析页面的其余部分,并在页面解析完毕后再按照顺序执行defer脚本。需要注意的是,由于async脚本的执行不会等待页面解析完毕,所以它们的执行顺序是不确定的。因此,async属性适合用于独立的脚本,而不适合有依赖关系的脚本。 阅读详情

相关推荐

【实战指南】从零构建UNet多分类分割数据集:标注、转换与训练全流程

本文提供了一份从零构建UNet多分类分割数据集的完整实战指南。详细介绍了使用Labelme进行图像标注的核心技巧与规范,并通过Python脚本将标注结果转换为模型可用的VOC格式。最后,指导如何修改经典的PyTorch版UNet代码,以适配自定义数据集并进行训练与测试,帮助读者完成从数据准备到模型训练的全流程。

arduino9maker的博客 287

浏览器环境中javascript加载执行顺序及注意点

1、html中通过script标签引入的javascript代码。 这种js代码是自上而下执行的,不论其加载快慢,始终都是按照顺序执行。 2、不要在加载脚本中使用document.write插入任何javascript代码。 因为这种方式写入的JS代码在执行流程中会出现一些问题,所以最好就是不要使用这种方式在加载过程中插入JS代码。 外部脚本:通过script src引入。 内部脚本:直接script内嵌。 注:document.write写入内容的位置还存在一个问题,加入在<head&.

lengye7的博客 3858

Eigen 直线拟合/曲线拟合/圆拟合/椭圆拟合

使用Eigen库进行直线拟合是数据分析和科学计算中的常见任务,主要通过最小二乘法实现。该代码演示了二维空间中的直线拟合,输出斜率和截距。

深之JohnChen的专栏 1594

如何保证script标签的加载顺序

本章博文主要解决script标签的加载顺序问题。

李卓书 2729

海思Hi3519A开发:DSP开发指南

通过创建DSP项目、实现算法、编译调试等步骤,开发者可以充分利用Hi3519A芯片集成的DSP,实现各种音视频处理功能。通过以上示例,我们可以看到在Hi3519A开发平台上进行DSP开发是一项强大而灵活的任务。在调试过程中,可以使用调试工具提供的功能,如断点设置、变量查看等,以便更好地理解和优化DSP算法的执行过程。在Hi3519A开发平台上,我们可以利用DSP的高性能计算能力来加速这些算法的执行。在实际的DSP开发中,算法的实现可能更加复杂,需要结合具体的项目需求进行。3.2 DSP算法实现。

QoTypescript的博客 1495

Unreal5从入门到精通之Landscape地形系统

虚幻引擎 5 (UE5) 能够利用其强大的地形编辑工具套件创建大规模的地形世界。使用地形工具可以创建身临其境的户外地形,这些地形经过优化,可在多种不同设备上保持可播放的帧速率。

TxNet 4142

JS中script脚本的执行顺序

JS中script脚本的执行顺序 在HTML中引入script脚本时,最普通的用法是直接引用,此时浏览器按顺序解析HTML,当解析到script的位置时,加载脚本并在加载完毕时立即执行脚本,在加载和执行的过程中会暂停HTML的解析。此种方法的问题是一旦因为某些原因导致脚本的加载时间过长,会影响页面的渲染,降低用户体验。所以在script标签中存在两个参数async和defer,可以控制脚本的加载和执行时间。 async async表示异步,script标签中有async参数时,浏览器会在解析到此处时异步加载

qq_38446108的博客 1524

大厂硬件机试选择题与判断题解析-卷1

本文精选30道硬件工程师机试题目,涵盖模拟电路、数字电路、PCB设计三大方向。模拟电路部分重点考察运算放大器、滤波器、整流电路等核心知识;数字电路部分聚焦计数器、电平转换等关键技术;PCB设计部分强调高速信号处理、阻抗控制等实践要点。题目均来自华为、小米等大厂真题,剔除基础题,每道题附详细解析,包括正确答案推导过程及相关公式说明。特别针对易错概念(如负反馈类型判断、Q值与带宽关系等)进行重点解析,帮助考生系统掌握硬件设计的核心考点和解题思路。

启芯硬件的博客 678

JavaScript执行顺序总结

js的执行顺序

qq_41872385的博客 5540

STM32Cube高效开发教程<基础篇>(一)----概述

一、 STM32系列器件和开发工具发展历史声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。本专栏博客参考《STM32Cube高效开发教程(基础篇)》,有意向的读者可以购买正版书籍辅助学习,本书籍由王维波老师、鄢志丹老师、王钊老师倾力打造,书籍内容干货满满。一、 STM32系列器件和开发工具发展历史。

我的博客 187

23、管状剪纸结构的研究与功能生成连杆机构的综合设计

本文研究了管状剪纸结构的压缩运动特性,通过剪纸技术将非刚性可折叠的Yoshimura和Kresling折纸结构转化为刚性可折叠结构,并提出径向可闭合剪纸(RC-kiri)构型。推导了位移与折叠角之间的数学关系,设计了带外部LET接头的RC-kiri模型,建立了力-位移理论模型并通过Abaqus进行有限元验证,制作了3D打印物理模型以测量直径变化。同时,研究了四杆和六杆功能生成连杆机构的综合设计方法,基于负闭合运动链和最小二乘法实现函数生成。结果表明理论、仿真与实验整体吻合良好,误差来源得到分析,为机器人、机

nokia的博客 167

html解析和渲染过程 与 Script标签和脚本执行顺序

几个首要特性: script标签(不带defer或async属性)的会阻止文档渲染。相关脚本会立即下载并执行。 document.currentScript可以获得当前正在运行的脚本(Chrome 29+, FF4+) 脚本顺序再默认情况下和script标签出现的顺序一致 有defer或async属性(defer和async没有完全兼容所有浏览器) 仅有async...

weixin_34137799的博客 481

详解Agent Skills:让AI拥有更多专业能力(什么是Agent Skills?如何创建?如何使用?如何获取?)

本文分享如何将零散指令沉淀为可复用的 AI 能力模块🧩,介绍什么是Agent Skills?如何创建?如何获取?📚

XiaoqiangClub的博客 1269

script标签中的defer和async

普通script: 文档解析的过程中,如果遇到script脚本,停止页面的解析渲染, 下载script脚本。 如果是多个script脚本, 近似于同时并行下载script脚本。 不论script脚本哪个先下载好, 都按照html中的先后顺序依此执行。 即如果后面的script脚本先下载好, 要等前面的script脚本下载好并执行后, 才能执行。 执行script脚本时, 也是停止页面的解析渲染。 执行完script脚本, 继续页面的解析渲染。 执行完script脚本和页面解析渲染完, 才会...

chenrongwei92的博客 9715

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

script标签中的defer和async属性的区别

如果script标签中没有defer或async属性,浏览器在渲染中遇到script标签就会停止渲染,下载执行js代码,等待JS执行完毕后,浏览器再从中断的地方恢复渲染。这就会造成浏览器阻塞,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然在当下,并不是说 script 标签必须放在底部,因为你可以给 script...

diwang_718的博客 1095

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

图解 script 标签中的 async 和 defer 属性

async defer scirpt 阻塞渲染

guxin_duyin的博客 681

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

script标签中的async和defer

当浏览器遇到带有 async 属性的 script 时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器会暂停解析,先让 JS 引擎执行代码,执行完毕后再进行解析。当浏览器遇到带有 defer 属性的 script 时,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器不会暂停解析并执行 JS 代码,而是等待 HTML 解析完毕再执行 JS 代码。

x0926的博客 874

按照顺序执行_动态插入的script脚本执行时间

在一些场景我们会动态插入script标签加载js。譬如某个js文件不是很重要,并不是整个页面需要的脚本,可能只是某个功能需要的,这个功能可能是用户点击了某个按钮才触发,入口比较深。且和你页面本身的结构不同类,譬如你是基于react的页面,这个功能的js是jquery插件。这种js文件我一般采用动态加载方式引入。如果你用js动态插入script,那么它什么时候执行呢,如果插入多个scrip...

weixin_39978749的博客 441

script标签

script 元素既可以包含脚本语句,也可以通过 src 属性指向外部脚本文件。默认情况下script标签的会阻止文档渲染,相关脚本会立即下载并执行。 属性 在HTML5中script主要有以下几个属性:async,defer,charset,src,type async(可选):     关键词:外部文件,异步下载,异步执行;     当标签中包含这个属性时会立即下载脚本(外部...

weixin_30617797的博客 163

script 标签中的 async 和 defer 的区别

在前端开发中,<script>标签的async和defer属性均用于优化脚本加载与页面渲染的关系,避免脚本阻塞页面解析,但二者在上存在关键区别。

jj1245_的博客 1097

script 标签中 defer 和 async 的区别

2.3.

我的博客 227

script标签中的属性

script标签中defer和async属性的区别script标签中defer和async属性的区别 script标签中defer和async属性的区别 script标签存在两个属性,defer和async,因此script标签的使用分为三种情况: 1. 没有defer或async属性,浏览器会立即加载并执行相应的脚本。也就是说在渲染script标签之后的文档之前,不等待后续加载的文档元素,读到就开始加载和执行,此举会阻塞后续文档的加载;    ①【如果放在head头里面引入,异步加载资源,但会阻塞的渲染,

dou_xiaobao的博客 997

script标签的知识

script标签的知识 script标签的执行顺序 script 是按照它们出现的顺序被执行的,执行时会阻塞程序运行,建议页面实现类的js放到body之前,动作、交互、事件驱动、对于dom属性的访问操作可以放在body的dom之后尾标签之前。这样会加快网页的加载速度。 script标签的async和defer属性 HTML5 添加了两个工具来控制脚本的执行。 async 表示“不用马上执行它”。更具体地它表示:我不介意你在整个网页加载完成之后执行这个脚本,把它放在其他脚本执行之后。这对于统计

在下魔王ii的博客 1388

【JS】script标签defer和async

【JS】script标签defer和async

owo_ovo的博客 553
上一篇: Mac 终端命令大全
下一篇: 细数前端中的一些黑科技
MR_LP
博客等级 码龄11年 236粉丝 89原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值