script 标签应放在 前最稳妥;若放 中须加 defer 属性,避免 async 和 window.onload;同时需检查 canvas 存在性、ID 一致性、CSS 显示状态及资源加载完成后再调用 getContext、drawImage 或 play。

script 标签放在哪儿才不报 document.getElementById 为 null
HTML5 小游戏依赖 DOM 元素(比如 )初始化,如果 放在 里又没加 defer 或 async,脚本执行时 还没被解析,document.getElementById('game') 必然返回 null。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 把游戏脚本
放在前——最稳妥,无需判断时机 - 若必须放
,加defer属性:,确保 DOM 解析完成后再执行 - 避免用
async,它不保证执行顺序,可能在 DOM 就绪前就运行了 - 不用
window.onload做兜底——它等所有资源(图片、字体)加载完才触发,延迟明显;优先用DOMContentLoaded
Canvas 元素缺失或 ID 写错导致 getContext 报错
常见错误现象是控制台报 Cannot read property 'getContext' of null,本质是获取 canvas 失败后直接调用了 .getContext()。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 检查 HTML 中
是否存在,且id和 JS 里传给document.getElementById()的字符串**完全一致**(区分大小写) - JS 中加一层防御性判断:
const canvas = document.getElementById('game'); if (!canvas) { console.error('Canvas with id "game" not found'); return; } const ctx = canvas.getContext('2d'); - 确认 canvas 没被 CSS 隐藏(如
display: none或visibility: hidden),虽然不影响getContext,但会导致渲染不可见
音频/图像资源加载未完成就调用 drawImage 或 play
小游戏常在 init() 或主循环中直接使用图片或音频对象,但若资源尚未加载完成,drawImage 可能静默失败,audio.play() 则抛 DOMException: The element has no supported sources 类错误。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 图片用
img.onload确保加载完成再加入资源池:const img = new Image(); img.src = 'player.png'; img.onload = () => { resources.player = img; }; - 音频推荐用
Promise封装加载逻辑,避免在未 resolve 前调用play() - 不要依赖“资源路径存在”就认为可用——本地开发时路径对但跨域限制也可能让
img.naturalWidth === 0 - 可加简易加载状态页,在所有关键资源
onload后再启动游戏循环
WebGL 上下文创建失败:getContext('webgl') 返回 null
不是所有设备都支持 WebGL,尤其旧 Android 浏览器、某些企业内网 IE 兼容模式,或显卡驱动被禁用时,canvas.getContext('webgl') 会返回 null,后续调用任何 WebGL API 都会报错。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 永远检查返回值:
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); if (!gl) { console.error('WebGL not supported'); fallbackToCanvas2D(); return; } -
experimental-webgl是旧版 Chrome/Safari 的遗留标识,现代浏览器已统一为webgl,但保留兼容写法无害 - 注意:部分浏览器(如 iOS Safari)对 WebGL 1.0 支持较好,但默认禁用 WebGL 2.0,需显式请求:
canvas.getContext('webgl2')并单独判断 - 移动端真机调试时,别只信桌面 Chrome 的模拟器结果——实际 GPU 能力差异很大











