一直对js的加载和执行过程比较模糊,现在从几个简单例子看看javascript的加载和执行过程。
例一:
<script type="text/javascript">
alert($); // error: $未定义,后面的脚本也无法执行
alert("我要执行");//不执行
</script>
<script src="http://tp.jrj.com.cn/js/jquery.js"></script>
<script type="text/javascript">
alert($); // function
</script>
结果及分析:script按顺序加载,每个script加载完即执行,如果执行有错会终止当前script的执行,对其它script没有影响。
jquery加载完成才执行后面的alert($);
例二:
<script type="text/javascript">
alert(i); // undefined
var i = 1;
alert(i);
</script>
输出结果是 undefined,这是因为执行前script引擎先对脚本片段就行了"预解析"。预解析发生在语法分析阶段,语法分析得到变量表varDecls,函数funDecls,父级引用upvalue
等语法分析结构,并保存在语法树中。从上到下执行,虽然执行环境中已经有了i的变量定义但未初始化,所以输出为undefined
例三:
<script type="text/javascript">
alert(i); // error: i未定义
i = 1;
alert(i);
</script>
执行报错。执行环境的scriptObject上找不到i,JS引擎再沿着scriptObject的upvalue往上寻找,最终在全局环境的scriptObject上都找不到,就产生运行时错误,终止脚本段执行。
再来看
<script src="http://tp.jrj.com.cn/js/jquery.js"></script>
<div style="border:1px solid red;width:100px;height:100px">
1111
</div>
<img src="http://www.meinvnv.com/uploads/allimg/100325/1_100325043702_1.jpg"/>
<script type="text/javascript">
alert($); // function
</script>
jquery加载完后div才被渲染,同样img也是在jquery加载完后加载的。script加载执行时阻塞页面的渲染和资源加载。脚本可能改变文档流,甚至跳转页面,所以浏览器暂停是合理的。
小结:
1) 如果一个文档流中包含多个script代码段(用script标签分隔的js代码或引入的js文件),运行顺序是:
step1. 加载、读入第一个代码段
step2. 做语法分析,对var变量和function定义做“预解析”,
有错则报语法错误(比如括号不匹配等),并跳转到step4
step3. 执行代码段,有错则报错(比如变量未定义)
step4. 如果还有下一个代码段,则读入下一个代码段,跳到step2
step5. 结束
2) 脚本片段执行时,阻塞后面资源的渲染和加载。