async、defer属性对内嵌JavaScript的script标签是否生效?与setTimeout等效吗?
问题:内嵌
<script>的async/defer属性是否生效?与setTimeout(0)效果一致吗? 我了解带src的外部<script>标签中defer和async的工作机制,但想知道这两个属性对内嵌JavaScript是否有相同效果?如果有,我认为以下两个示例的结果应该一致,这个理解正确吗?
示例1:
<script async> doStuff(); </script>
示例2:
<script> setTimeout(doStuff, 0); </script>
答案
核心结论
- 内嵌
<script>上的async和defer属性完全无效,浏览器会直接忽略它们。 - 你给出的两个示例行为并不一致,具体差异如下:
详细解析
- 内嵌script的
async/defer属性为何无效async和defer是专为带src的外部脚本设计的,用于协调外部脚本的加载、执行与HTML解析的时机。对内嵌脚本而言,这两个属性没有任何实际作用——浏览器遇到内嵌<script>时,会立刻暂停HTML解析,同步执行脚本内容,无论是否添加这两个属性。
所以示例1的代码,实际执行效果和去掉async完全相同:doStuff()会被同步立即执行,并且阻塞后续的HTML解析流程。
- 与
setTimeout(0)的本质差异
示例2中,setTimeout(doStuff, 0)会把doStuff()推入浏览器的任务队列。当前内嵌脚本执行完成后,浏览器会先恢复HTML解析,等当前宏任务执行完毕(或HTML解析完成),才会取出任务队列中的doStuff()执行。
两者的关键区别:
- 带
async的内嵌script:同步执行,阻塞HTML解析 - 用
setTimeout(0)的script:异步执行,不阻塞HTML解析,脚本执行完成后才触发doStuff
额外提示
如果想让内嵌脚本实现类似外部async脚本的异步执行效果,可以选择:
- 把代码放到外部JS文件中,添加
async属性 - 监听
DOMContentLoaded事件触发代码 - 低优先级任务使用
requestIdleCallback
内容的提问来源于stack exchange,提问作者ivi_does_it
相关产品推荐
相关产品推荐

