JavaScript脚本执行顺序无详细指南?代码出现异常行为求解析
JavaScript语句执行顺序与你的Canvas resize问题解析
一、先掰明白JavaScript执行顺序的核心逻辑
JavaScript是单线程的,核心规则就是同步任务按顺序跑,异步任务排队等触发:
- 同步任务:像你写的获取DOM、给Canvas设初始宽高、变量赋值这些,都会在主线程里严格按照代码书写的顺序依次执行,浏览器调试看到的顺序完全没问题。
- 异步任务:比如
onresize这种事件回调,属于“宏任务”范畴,它不会抢同步任务的跑道,得等所有同步任务执行完,再等对应的事件(窗口大小变化)触发,才会被拉进执行队列跑起来。
你的代码同步流程是实打实按顺序走的:
- 先拿到页面上的Canvas元素
- 把Canvas的宽高设成当前窗口的尺寸
- 把
window存到变量w里 - 给窗口的resize事件绑定回调函数
二、你遇到的怪异行为,大概率是这几个Canvas常见坑
虽然你没说具体是啥怪异表现,但结合Canvas resize的高频问题,我猜可能是下面某一种:
- 绘图内容凭空消失:当你修改Canvas的
width/height时,它的绘图上下文(就是getContext('2d')拿到的那个对象)会被重置,之前画的东西直接清空。如果你的代码里有绘图逻辑,得在resize回调里重新执行一遍。 - Canvas拉伸变形:如果你的Canvas在CSS里设置了宽高,JS里设的
width/height是它的实际像素尺寸,CSS的是显示尺寸,两者不匹配就会拉伸。比如CSS写了width:100%,JS又设width = window.innerWidth,就容易冲突。 - resize时卡顿:窗口拖动过程中resize会连续触发,回调函数疯狂执行,就会导致页面卡顿,这时候需要用“防抖”来限制执行频率。
三、给你优化后的代码参考
针对这些常见问题,调整后的代码大概是这样:
// 先拿到Canvas和绘图上下文(如果需要绘图的话) var cvs = document.getElementById('cvs'); var ctx = cvs.getContext('2d'); // 把设置尺寸和重绘的逻辑封装成函数,方便复用 function setCanvasSize() { // 先清空之前的绘图(按需选择) ctx.clearRect(0, 0, cvs.width, cvs.height); // 设置Canvas的实际像素尺寸 cvs.width = window.innerWidth; cvs.height = window.innerHeight; // 这里放你的绘图逻辑,resize后重新画 drawMyContent(); } // 防抖函数:让resize回调不会疯狂触发,100ms内只执行最后一次 function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } // 页面加载完成后先执行一次,设置初始尺寸 setCanvasSize(); // 给resize事件绑定防抖后的函数 window.onresize = debounce(setCanvasSize, 100); // 示例绘图函数,替换成你自己的逻辑就行 function drawMyContent() { ctx.fillStyle = '#2ecc71'; ctx.fillRect(0, 0, cvs.width, cvs.height); }
四、再补充几个执行顺序的细节点
你说全网找不到详细指南,我再给你划几个容易踩坑的重点:
- 变量提升:用
var声明的变量(比如var cvs)会被“提升”到当前作用域的最顶部,但赋值还是按代码顺序来。比如你如果在var cvs = ...之前写console.log(cvs),会输出undefined,因为声明提前了但赋值还没执行。 - DOM操作时机:如果你的Canvas是动态生成的(不是一开始就在HTML里),那
document.getElementById('cvs')会返回null,这时候得把代码放在DOMContentLoaded事件里,确保DOM加载完成后再执行。 - 事件回调的执行时机:
onresize回调不会在页面加载时执行,只有当窗口大小真的变化了,它才会被加入任务队列,等主线程空闲的时候才会跑。
内容的提问来源于stack exchange,提问作者Paul K
相关产品推荐
相关产品推荐

