HTML中的Javascript
<script>
元素属性
src
属性: 指向要执行的脚本代码的外部文件,即其值为外部脚本地址。charset
属性: 使用src
属性指定的代码所使用的字符集。这个属性很少用,字符集如:UTF-8、ISO-8859-1等。crossorigin
属性: 配置相关请求的CORS
设置,默认不使用该属性,其属性值有:crossorigin="anonymouse"
: 表示对脚本文件中的请求中不设置用户凭据。crossorigin="use-credentials"
: 表示设置凭据标志,意味着发出的请求中会包含用户凭据。
integrity
属性: 这个单词本身就是完整性、诚信
的意思, 添加该属性则表示允许比对接收到的资源和指定的加密签名(是一个哈希值)以验证子资源完整性(SRI,subresource integrity)。若接收到的资源的签名和这个属性指定的签名不匹配,则页面会报错,脚本不会执行。
integrity
属性可以用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。
type
属性: 代替废弃的language
属性,表示代码块中的脚本语言的内容类型(MIME,Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)。type
的值默认是text/javascript
,由于原先的text/javascript
和text/ecmascript
已废弃,因此其默认值为application/x-javascript
,有效的其他值为application/javascript
和application/ecmacript
;type
还有一个值为module
: 则代码会被认为是ES6模块,而此时代码中次才能出现import
和export
关键字。当然,对于不支持ES6模块的浏览器,可以设置nomodule
属性,而支持es6模块的浏览器则会不加载指定的脚本。如下所示:1
2<script type="module" src="main.js"></script>
<script nomodule src="fallback.js"></script>
还有关于
nonce
和referrerpolicy
属性,这里不再赘述,用到了再查吧,先掌握上述属性。
关于无属性的script和带有
async
、defer
属性的scirpt区别,请参考知乎上的一个问答,我觉得总结很不错,这里我搬运一下,原作者是山行者
。
问题
:在html
中会遇到以下三类script
:
1 | <script src='xxx'></script> |
- 先来看没有任何属性的
script
:浏览器在解析 HTML 的时候,如果遇到一个没有任何属性的script
标签,就会暂停解析,先发送网络请求获取该 JS 脚本的代码内容,然后让 JS 引擎执行该代码,当代码执行完毕后HTML恢复解析。整个过程如下图所示:
- 再来看
async script
:async本身是异步的意思,当浏览器遇到带有 async 属性的 script 时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器会暂停解析,先让 JS 引擎执行代码,执行完毕后再进行解析,图示如下:
当然,如果在 JS 脚本请求回来之前,HTML 已经解析完毕了,那就啥事没有,立即执行 JS 代码,如下图所示:
所以 async 是不可控的,因为执行时间不确定,你如果在异步 JS 脚本中获取某个 DOM 元素,有可能获取到也有可能获取不到。而且如果存在多个 async 的时候,它们之间的执行顺序也不确定,完全依赖于网络传输结果,谁先下载下来就执行谁。
- 最后来看
defer script
:defer本身有推迟、延期的意思。当浏览器遇到带有 defer 属性的 script 时,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析 HTML,一旦网络请求回来之后,如果此时 HTML 还没有解析完,浏览器不会暂停解析并执行 JS 代码,而是等待 HTML 解析完毕再执行 JS 代码,图示如下:
如果存在多个 defer script 标签,浏览器(IE9及以下除外)会保证它们按照在 HTML 中出现的顺序执行,不会破坏 JS 脚本之间的依赖关系。
因此总结如下:
script标签 | js执行顺序 | 是否阻塞解析html |
---|---|---|
<script> |
在html中的顺序 | 阻塞 |
<script async> |
网络请求返回顺序 | 可能阻塞,也可能不阻塞 |
<script defer> |
在html中书写的顺序 | 不阻塞 |