← 返回目录

3. 脚本位置与入口函数

浏览器读网页是从上往下一行行读的。如果你把 JS 写在最上面(head 里),它一上来就想找下面 body 里的那个 div——可那时那个 div 还没被读到、还没出生!你就会拿到一个空空如也的 null(什么都没有),一操作就报错。这是新手最常踩的坑,这页专门治它。

3.1 互动演示(亲自体会 null)

我是 body 里的一个盒子(id=demoBox)
填个 id 点按钮:找得到就打印标签,找不到就是 null。

3.2 知识点逐条讲解

① 为什么写在 head 里会拿到 null?

想象你提前一小时去饭桌上夹菜——菜还没炒好,筷子当然夹到空气。null 就是"空气"的意思:找到了个寂寞。

<head>
  <script>
    let box = document.getElementById('demoBox'); // 现在就去找,可它还没被读到
    console.log(box);          // null!下面的 div 还没出生,啥都没找到
    box.style.color = 'red';   // 报错:你不能改"空气"的颜色
  </script>
</head>
<body>
  <div id="demoBox">...</div>  <!-- script 读到这行时,它还没出生 -->
</body>
	

② 办法一:把 JS 放到 body 最底下

最省事:等菜全上完了(HTML 全读完),你再动筷子(执行 JS),想找谁都在。

<body>
  <div id="demoBox">...</div>
  <script>
    // 到这里,body 里的元素全都已经"出生"了
    let box = document.getElementById('demoBox'); // 这时再找,它已经出生了
    console.log(box);   // 正常拿到,不再是 null
  </script>
</body>
	

③ 办法二:等"树长好了"再执行(DOMContentLoaded

如果你就是想把 JS 放上面,那就跟浏览器说一句:"等这棵树全建好了,你再帮我跑这段代码。"这句话就是 DOMContentLoaded

// 哪怕 JS 写在 head 里也不怕
document.addEventListener('DOMContentLoaded', function () { // 等树建好再跑这个函数
  // 这个函数,会在"树建好了"那一刻才执行
  let box = document.getElementById('demoBox'); // 这时元素已出生,找得到
  console.log(box);   // 正常拿到
});
	

DOMContentLoadedwindow.onload 区别(必背)

哪句话什么时候跑感受
DOMContentLoaded标签树建好了就跑,不等图片,推荐用
window.onload图片等所有资源都加载完才跑,而且只能写一个

如果你 window.onload 写了两次,就会发现前面那段不跑了。因为 onload 像个单人床,躺第二个人会把第一个挤下去;想多段代码都在加载后跑,就用 DOMContentLoaded(能排好几个)。

实战:用在哪 / 常见坑 / 怎么解决

① 用在哪:页面加载完要操作 DOM 的脚本都要等入口事件;统计埋点初始化。

② 常见坑:拿元素得 null,一操作就报 Cannot read property of null。

③ 怎么解决:把 script 放 body 底部,或用 DOMContentLoaded 包住;找不到先打印看是不是 null。

一句话记住:拿不到元素 90% 是 JS 写太早;要么把 JS 放 body 最底下,要么用 DOMContentLoaded 说"等树建好再跑";window.onload 更慢、还只能写一个。