普通视图

发现新文章,点击刷新页面。
今天 — 2026年2月2日技术

函数为何能“统治”JavaScript:一等公民与高阶函数的工程化用法

作者 swipe
2026年2月1日 22:38
引言:为什么团队里“会用函数”和“用好函数”差距这么大 在业务迭代快、多人协作密集的前端项目里,你一定见过两类代码: 一类是“能跑就行”的循环 + if + push:逻辑散在各处,重复多、难复用、改
昨天 — 2026年2月1日技术

既然有了 defer,我们还需要像以前那样把 <script>标签放到 <body>的最底部吗?

作者 Smilezyl
2026年2月1日 17:51

既然有了 defer,我们还需要像以前那样把 <script> 标签放到 <body> 的最底部吗?如果我把带 defer 的脚本放在 <head> 里,会有性能问题吗?

核心答案

不需要了。 使用 defer 属性后,把 <script> 放在 <head> 里不仅没有性能问题,反而是更优的做法

原因:

  1. defer 脚本会并行下载,不阻塞 HTML 解析
  2. 脚本执行会延迟到 DOM 解析完成后,但在 DOMContentLoaded 事件之前
  3. 放在 <head> 里可以让浏览器更早发现并开始下载脚本

深入解析

浏览器解析机制

传统 <script>(无 defer/async):
HTML 解析 ──▶ 遇到 script ──▶ 暂停解析 ──▶ 下载脚本 ──▶ 执行脚本 ──▶ 继续解析

defer 脚本:
HTML 解析 ────────────────────────────────────────────▶ DOM 解析完成 ──▶ 执行脚本
     └──▶ 并行下载脚本 ──────────────────────────────────────────────────┘

为什么 <head> 里的 defer 更好?

位置 发现脚本时机 开始下载时机
<head> 解析开始时 立即
<body> 底部 解析接近完成时 较晚

放在 <head> 里,浏览器可以在解析 HTML 的同时下载脚本,充分利用网络带宽

常见误区

误区 1: "defer 脚本放 <head> 会阻塞渲染"

  • 错误。defer 脚本的下载和 HTML 解析是并行的

误区 2: "放 <body> 底部更保险"

  • 这是 defer 出现之前的最佳实践,现在已过时
  • 放底部反而会延迟脚本的发现和下载

误区 3: "defer 和放底部效果一样"

  • 不一样。放底部时,脚本下载要等到 HTML 解析到那里才开始
  • defer 在 <head> 里可以更早开始下载

defer vs async vs 传统方式

                    下载时机        执行时机              执行顺序
传统 script         阻塞解析        下载完立即执行         按文档顺序
async              并行下载        下载完立即执行         不保证顺序
defer              并行下载        DOM 解析完成后        按文档顺序

代码示例

<!-- ✅ 推荐:defer 脚本放在 <head> -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>页面标题</title>
  <!-- 浏览器立即发现并开始下载,但不阻塞解析 -->
  <script defer src="vendor.js"></script>
  <script defer src="app.js"></script>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <!-- HTML 内容 -->
</body>
</html>

<!-- ❌ 过时做法:放在 body 底部 -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>页面标题</title>
</head>
<body>
  <!-- HTML 内容 -->

  <!-- 要等 HTML 解析到这里才开始下载 -->
  <script src="vendor.js"></script>
  <script src="app.js"></script>
</body>
</html>

验证下载时机的方法

打开 Chrome DevTools → Network 面板,观察脚本的下载开始时间:

  • <head> 里的 defer 脚本:在 HTML 下载初期就开始
  • <body> 底部的脚本:在 HTML 解析接近完成时才开始

面试技巧

可能的追问方向

  1. "defer 和 async 有什么区别?"

    • async 下载完立即执行,不保证顺序
    • defer 等 DOM 解析完才执行,保证顺序
  2. "多个 defer 脚本的执行顺序是怎样的?"

    • 按照在文档中出现的顺序执行
    • 即使后面的脚本先下载完,也会等前面的
  3. "defer 脚本和 DOMContentLoaded 的关系?"

    • defer 脚本在 DOM 解析完成后、DOMContentLoaded 触发前执行
  4. "什么情况下还是要放 body 底部?"

    • 需要兼容不支持 defer 的古老浏览器(IE9 以下)
    • 现代开发中基本不需要考虑

展示深度的回答方式

"defer 放 <head> 不仅没有性能问题,反而是更优的选择。因为浏览器的预加载扫描器(Preload Scanner)可以在解析 HTML 的早期就发现这些脚本并开始下载,充分利用网络带宽。而放在 <body> 底部的话,脚本的发现时机会延后,相当于浪费了并行下载的机会。"

一句话总结

defer 脚本放 <head> 是现代最佳实践:更早发现、并行下载、不阻塞解析、按序执行。

❌
❌