HTML中最熟悉的陌生人:<script>标签必知必会

<script>标签用于在HTML中引入js,本文主要讨论三方面:

  1. script标签在不同位置引入的区别(如在head引入和在body引入,在body开头与最后引入)
  2. script标签的三种引入方式(default,async,defer),
  3. script标签模块化(type='module')

加载与执行的区别

脚本的加载(Loading)与执行(Execution)是两个独立的概念,它们的行为和影响因素不同,理解这一点对我们后面的讨论至关重要.

  • 加载: 浏览器从服务器获取脚本文件(如 script.js)的过程,涉及网络请求和资源下载。
  • 执行: 浏览器解析并运行脚本中的 JavaScript 代码。

引入位置区别

<head> 中引入或在<body>最开始引入

  • 浏览器会暂停 HTML 解析,立即加载并执行脚本,执行完成后才继续解析 DOM。

  • 若脚本体积大或网络慢,会导致页面渲染阻塞(白屏时间长)。

  • 如果脚本尝试操作 DOM(如 document.getElementById),可能因为 DOM 还未解析而找不到元素,导致错误。

  • 适用场景

    • 需要尽早执行不依赖 DOM 的脚本(如某些性能监控、日志上报代码)。
    • 一般不推荐,除非有特殊需求。

<body> 底部引入

  • 不阻塞 DOM 解析 ,浏览器会先解析完整的 HTML,最后再加载和执行脚本,不会影响页面渲染速度。用户能更快看到页面内容(减少 FCP,First Contentful Paint)。

  • 脚本执行时 DOM 已就绪 ,脚本运行时,整个 DOM 已经解析完成,可以安全操作 DOM 元素,无需等待 DOMContentLoaded 事件。

  • 适用场景

    • 推荐的经典做法,适用于大多数情况,特别是依赖 DOM 的脚本(如交互逻辑、初始化组件)。
    • 如果脚本较大,仍可能影响 DOMContentLoaded 事件触发时间。

三种引入

默认引入

遵循多个脚本按书写顺序依次加载并执行的原则。

defer

html 复制代码
<script src="script.js" defer></script>
  • 行为

    • 脚本异步加载 (不阻塞 HTML 解析),但会延迟到 DOM 解析完成后、DOMContentLoaded 事件前按顺序执行。
    • 适用于需要操作 DOM 或依赖其他脚本的场景。
  • 特点

    • 保证脚本的执行顺序(与书写顺序一致)。
    • 天然支持"等 DOM 就绪",类似 DOMContentLoaded

async

html 复制代码
<script src="script.js" async></script>
  • 行为

    • 脚本异步加载 (不阻塞 HTML 解析),加载完成后立即执行(可能中断 HTML 解析)。
    • 适用于独立脚本(如统计代码、第三方 SDK)。
  • 特点

    • 不保证执行顺序(谁先加载完谁先执行)。
    • 不适合操作 DOM 的脚本(可能 DOM 还未解析完)。

模块化type="module"

html 复制代码
<script type="module" src="module.js"></script>
  • 场景

    • 你的代码需要按模块化拆分,通过 import 引入其他模块或通过 export 暴露功能。

      html 复制代码
      <script type="module">
        import { utils } from './utils.js';
        import Component from './Component.js';
      </script>
  • 行为

    • 避免全局变量污染,依赖关系清晰,适合大型项目。
    • 默认具有 defer 行为(异步加载,DOM 解析后执行)。
    • 若显式添加 async(如 <script type="module" async>),则行为类似 async
  • 特点

    • 支持 ES6 模块语法(import/export)。
    • 自动启用严格模式。
    • 模块脚本默认延迟执行 ,且按依赖关系顺序执行

参考资料

  1. developer.mozilla.org/zh-CN/docs/...
  2. www.bilibili.com/video/BV1vA...
相关推荐
ZC跨境爬虫1 分钟前
模块化烹饪小程序开发日记 Day6:(菜谱列表接口开发与日志调试实践)
前端·javascript·css·ui·微信小程序·html
KaMeidebaby6 分钟前
卡梅德生物技术快报|适配体筛选技术架构演进:SPARK-seq 高通量平台原理与技术流程解析
大数据·前端·其他·百度·架构·spark·新浪微博
之歆12 分钟前
Day15_JavaScript DOM 事件完全指南:从基础到实战(上)
开发语言·javascript·ecmascript
todaycode13 分钟前
Vue + CPP项目
javascript·c++·vue.js
ZC跨境爬虫16 分钟前
跟着 MDN 学CSS day_7:(层叠优先级与继承)
前端·css·数据库·ui·html
Shadow(⊙o⊙)21 分钟前
qt信号和槽链接的接入与断开
开发语言·前端·c++·qt·学习
慕斯fuafua22 分钟前
JS——DOM操作
前端·javascript·html
忆林52025 分钟前
Jenkins前端打包构建老项目拯救指南
运维·前端·jenkins
GISer_Jing26 分钟前
深入解析 Three.js:从架构设计到 WebGPU 渲染革命
javascript·信息可视化·webgl
微祎_31 分钟前
写给新手的 triton-inference-server-ge-backend:昇腾Triton推理服务后端到底是啥?
前端·人工智能·cann