首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

JS 載入時機陷阱:為什麼

現象複現:一個經典的「找不到表單」報錯

學習《JavaScript 高級程序設計》表單章節時,按書中示例在 <head> 中編寫腳本獲取表單元素:

<!DOCTYPE html>
<html>
<head>
  <title>Form Fields Example</title>
  <script type="text/javascript">
    var form = document.getElementById("myForm");
    console.log(form.elements['color'].length); // Uncaught TypeError: Cannot read property 'length' of null
  </script>
</head>
<body>
  <form method="post" id="myForm">...</form>
</body>
</html>

控制台拋錯:Cannot read property 'length' of null。但將同樣代碼移至 </body> 前即正常運行。為什麼位置不同會導致行為差異?

根本原因:瀏覽器解析渲染的單線程、自上而下特性

瀏覽器解析 HTML 遵循深度優先、自上而下的單線程模型:

  1. 解析 <head>,遇到內聯 <script> → 暫停 DOM 構建,立即執行腳本。
  2. 此時 <body> 尚未解析,document.getElementById("myForm") 返回 null。
  3. 腳本執行完畢,繼續解析 <body> 構建 DOM 樹。

書中示例將腳本置於 </body> 前,保證執行時目標 DOM 已存在。

驗證實驗:多位置腳本執行順序與 DOM 可見性

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script>
    console.log(111); // 1. 最先打印
    console.log(document.getElementsByName("color").length); // 0
    console.log(document.getElementById("myForm")); // null
  </script>
</head>
<body>
  <form id="myForm"><input type="radio" name="color"></form>
  <script>
    console.log(222); // 2. 後打印
    console.log(document.getElementsByName("color").length); // 1
    console.log(document.getElementById("myForm").elements.length); // 1
  </script>
</body>
</html>

結論:僅操作 DOM 元素的腳本,必須放在該元素之後(或 </body> 前);純邏輯計算、函數定義、事件綁定(延遲執行)的腳本放在 <head> 無影響。

現代最佳實踐:告別位置依賴

方案原理適用場景
<script defer>HTML5 標準,延遲至 DOMContentLoaded 前執行,保持順序外部腳本,現代瀏覽器首選
<script async>異步下載,下載完成立即執行,順序不定獨立第三方腳本(統計、廣告)
window.onload / DOMContentLoaded事件回調保證 DOM 就緒內聯腳本兼容舊瀏覽器
模塊化構建Webpack/Vite 等打包工具自動注入 defer 或置於 body 底部工程化項目標配

核心原則:腳本執行時機必須晚於目標 DOM 構建完成。理解瀏覽器解析流程,是前端工程師避坑的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
欄目導航
Copyright © 程式碼之家 All Rights Reserved