一个JavaScript的小问题
本来要在网页里写这样一段测试代码:
<script> var canvas=document.getElementById("display"); var cxt=canvas.getContext("2d"); </script> <canvas id="display"></canvas> <button onclick="alert(typeof(cxt))"/>test</button>
结果一直给我报错,弄了我老半天。这才几行代码啊。
后来查到的解决办法是,把脚本放在页面元素后面,也即:
<canvas id="display"></canvas> <button onclick="alert(typeof(cxt))"/>test</button> <script> var canvas=document.getElementById("display"); var cxt=canvas.getContext("2d"); </script>
这样做的解释是:“浏览器在执行JavaScript代码时,不能同时做其它事情,即<script>每次出现都会让页面等待脚本的解析和执行(不论JavaScript是内嵌的还是外链的),JavaScript代码执行完成后,才继续渲染页面。这个也就是JavaScript的阻塞特性。”引用
第一段代码中执行getElementById()时,canvas元素还未渲染,当然获取到的对象只能为空。结论是:
1.为页面添加的脚本最好放在页面元素的后面(不论是内嵌脚本还是外链脚本),因为还未渲染的页面元素是无法被脚本所访问到的。HTML文档是从上到下顺序渲染的,而且每次遇到<script>都会产生阻塞效应。而<head>里面的脚本是会最先被执行,此时页面元素全部尚未渲染完毕,阻塞效应会大大影响页面的渲染速度,所以最好是将脚本放在</body>的前面,因为这时页面元素都已经渲染完毕;
2.当需要在脚本直接调用页面元素时,不要在脚本中调用处于脚本后的元素(也即未渲染的元素),或者将脚本移动到需调用的元素后(如上文的改动方式)。当然这种方式并不推荐,最好以添加响应函数的形式去调用元素。
也许是以前写MFC的时候,事件驱动的思想中毒太深,喜欢给什么页面元素都来个响应函数,所以平时还不会遇到这个问题。这次想偷懒,直接在响应函数外操作页面元素,结果反而出错了,囧。话说JavaScript的阻塞特性什么的,也太霸道了。。。
浙公网安备 33010602011771号