You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么script标签放在head中无法获取DOM元素,放在body末尾就正常运行?

问题原因解析

1 报错的根本原因

浏览器解析HTML页面的顺序是从上到下逐行执行:

  • 当你把script放在head标签末尾时,此时浏览器还没开始解析body里的内容,<video id="video">元素还没有被挂载到DOM树上,document.getElementById("video")的返回结果为null,后续尝试给null设置width属性,自然就抛出Cannot set properties of null (setting 'width')的错误。
  • 当你把script放在body标签末尾时,此时body里的所有DOM元素都已经解析完成,能正常获取到video元素,所以代码可以正常运行。

2 script放在head和body中的核心区别

两者的核心差异集中在执行时机和对页面性能的影响两个维度:

  • 执行时机不同:无特殊属性的普通script标签放在head中时,会在DOM解析、页面渲染前就加载并执行;放在body末尾的script会在所有DOM元素解析完成后才执行,不需要额外监听就能直接操作页面上的所有已生成元素。
  • 对渲染的影响不同:普通script标签的加载和执行会阻塞DOM解析和页面渲染,放在head中如果脚本体积大、执行逻辑重,会拉长用户的首屏白屏时间;放在body末尾不会阻塞首屏内容的渲染,用户感知的页面加载速度更快。

3 script标签放置位置的选择建议

不需要始终将script放在body末尾,可以根据场景判断:

  • 绝大多数和DOM操作相关、不需要提前执行的业务脚本,推荐放在body末尾,是兼容性最好、性能开销最低的方案。
  • 以下场景可以将script放在head中:
    • 全局基础配置类脚本,比如全局环境变量定义、前端框架的前置初始化配置
    • 首屏性能统计、异常监控类需要提前启动的脚本
    • 加了async/defer异步属性的第三方工具库,异步加载不会阻塞页面渲染

如果你需要把操作DOM的脚本放在head中,可以通过监听DOMContentLoaded事件避免找不到元素的问题,示例代码如下:

<script>
  var video;
  // 等待DOM完全解析完成后再获取元素
  document.addEventListener('DOMContentLoaded', function() {
    video = document.getElementById("video");
    changeVideoSize(); // 页面加载完成先执行一次尺寸适配
  })
  function changeVideoSize() {
    if(!video) return; // 兜底判断,避免元素未初始化时执行报错
    console.log("width is: ", window.innerWidth)
    if (window.innerWidth > 900) {
      video.width = "640";
      video.height = "480";
    } else {
      video.width = "320";
      video.height = "240";
    }
  }
  window.addEventListener("resize", changeVideoSize)
</script>

内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:15:03