JS执行顺序.docx
- 文档编号:8657269
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:13
- 大小:92.62KB
JS执行顺序.docx
《JS执行顺序.docx》由会员分享,可在线阅读,更多相关《JS执行顺序.docx(13页珍藏版)》请在冰豆网上搜索。
JS执行顺序
一直以来都是光知道写js,但其实对这东西并不怎么了解,只是知道用而已,稍微略深入的就不知道了。
这个是介绍js在页面上的执行顺序的,挺不错的,转载一下。
---------------------------异常美丽的分割线-------------------------------------------------------------------------------------------------------------------------------------
上一节是从JavaScript引擎的解析机制来探索JavaScript的工作原理,下面我们以更形象的示例来说明JavaScript代码在页面中的执行顺序。
如果说,JavaScript引擎的工作机制比较深奥是因为它属于底层行为,那么JavaScript代码执行顺序就比较形象了,因为我们可以直观感觉到这种执行顺序,当然JavaScript代码的执行顺序是比较复杂的,所以在深入JavaScript语言之前也有必要对其进行剖析。
1.6.1按HTML文档流顺序执行JavaScript代码
首先,读者应该清楚,HTML文档在浏览器中的解析过程是这样的:
浏览器是按着文档流从上到下逐步解析页面结构和信息的。
JavaScript代码作为嵌入的脚本应该也算做HTML文档的组成部分,所以JavaScript代码在装载时的执行顺序也是根据脚本标签
4.
5.
6.
7.
10.
11.
12.
13.
14.
15.
16.
17.
20.
21.
22.
23.
如果通过脚本标签
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
1.6.2预编译与执行顺序的关系
当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。
所以,就会出现当JavaScript解释器执行下面脚本时不会报错:
[javascript]viewplaincopy
1.alert(a); // 返回值undefined
2.var a =1;
3.alert(a); // 返回值1
由于变量声明是在预编译期被处理的,所以在执行期间对于所有代码来说,都是可见的。
但是,你也会看到,执行上面代码,提示的值是undefined,而不是1。
这是因为,变量初始化过程发生在执行期,而不是预编译期。
在执行期,JavaScript解释器是按着代码先后顺序进行解析的,如果在前面代码行中没有为变量赋值,则JavaScript解释器会使用默认值undefined。
由于在第二行中为变量a赋值了,所以在第三行代码中会提示变量a的值为1,而不是undefined。
同理,下面示例在函数声明前调用函数也是合法的,并能够被正确解析,所以返回值为1。
[javascript]viewplaincopy
1.f(); // 调用函数,返回值1
2.
3.function f(){
4. alert
(1);
5.}
但是,如果按下面方式定义函数,则JavaScript解释器会提示语法错误。
[javascript]viewplaincopy
1.f(); // 调用函数,返回语法错误
2.
3.var f = function(){
4.
5. alert
(1);
6.
7.}
这是因为,上面示例中定义的函数仅作为值赋值给变量f,所以在预编译期,JavaScript解释器只能够为声明变量f进行处理,而对于变量f的值,只能等到执行期时按顺序进行赋值,自然就会出现语法错误,提示找不到对象f。
虽然变量和函数声明可以在文档任意位置,但是良好的习惯应该是在所有JavaScript代码之前声明全局变量和函数,并对变量进行初始化赋值。
在函数内部也是先声明变量,然后再引用。
1.6.3按块执行JavaScript代码
所谓代码块就是使用
5.
6.
JavaScript解释器在执行脚本时,是按块来执行的。
通俗地说,就是浏览器在解析HTML文档流时,如果遇到一个
6.
7.
虽然说,JavaScript是按块执行的,但是不同块都属于同一个全局作用域,也就是说,块之间的变量和函数是可以共享的。
1.6.4借助事件机制改变JavaScript执行顺序
由于JavaScript是按块处理代码,同时又遵循HTML文档流的解析顺序,所以在上面示例中会看到这样的语法错误。
但是当文档流加载完毕,如果再次访问就不会出现这样的错误。
例如,把访问第2块代码中的变量和函数的代码放在页面初始化事件函数中,就不会出现语法错误了。
[javascript]viewplaincopy
1.
8.
9.
为了安全起见,我们一般在页面初始化完毕之后才允许JavaScript代码执行,这样可以避免网速对JavaScript执行的影响,同时也避开了HTML文档流对于JavaScript执行的限制。
注意
如果在一个页面中存在多个windows.onload事件处理函数,则只有最后一个才是有效的,为了解决这个问题,可以把所有脚本或调用函数都放在同一个onload事件处理函数中,例如:
[javascript]viewplaincopy
1.window.onload = function(){
2. f1();
3. f2();
4. f3();
5.}
而且通过这种方式可以改变函数的执行顺序,方法是:
简单地调整onload事件处理函数中调用函数的排列顺序。
除了页面初始化事件外,我们还可以通过各种交互事件来改变JavaScript代码的执行顺序,如鼠标事件、键盘事件及时钟触发器等方法,详细讲解请参阅第14章的内容。
1.6.5JavaScript输出脚本的执行顺序
在JavaScript开发中,经常会使用document对象的write()方法输出JavaScript脚本。
那么这些动态输出的脚本是如何执行的呢?
例如:
[html]viewplaincopy
1.document.write('
9.
10.
13.
14.外部JavaScript文件(test1.js)的代码如下所示。
15.var n = 1;
16.alert(n);
在IE浏览器中的执行顺序如图1-6所示。
图1-6IE7浏览器的执行顺序和提示的语法错误
在符合DOM标准的浏览器中的执行顺序与IE浏览器不同,且没有语法错误,如图1-7所示的是在Firefox3.0浏览器中的执行顺序。
图1-7Firefox3浏览器的执行顺序和提示的语法错误
解决不同浏览器存在的不同执行顺序,以及可能存在Bug。
我们可以把凡是使用输出脚本导入的外部文件,都放在独立的代码块中,这样根据上面介绍的JavaScript代码块执行顺序,就可以避免这个问题。
例如,针对上面示例,可以这样设计:
[javascript]viewplaincopy
1.
4.
5.
12.
13.
这样在不同浏览器中都能够按顺序执行上面代码,且输出顺序都是1、2、3、4和5。
存在问题的原因是:
输出导入的脚本与当前JavaScript代码块之间的矛盾。
如果单独输出就不会发生冲突了。
-------------------------------------------------------------------------------------------------------------
以下出处为:
关于作用域的问题跟注意事项:
对于从未声明过的对象,如果尝试给它赋值,会隐式的将其声明为全局对象:
[javascript]viewplaincopy
1.(function(){
2. s = "abc";
3.})()
4.alert(s);
会弹出abc
如果尝试读一个未声明的对象,则js会报错。
如:
[javascript]viewplaincopy
1.alert(a);//不会有弹出框,会报错
js报错会直接导致不继续往下运行,有时候查起来真有点麻烦
但这是个铁律,所以以下写法儿是经常容易犯的错误:
[javascript]viewplaincopy
1.if(!
a){
2.//dosomething,,,,,
3.}
有时候这样写的初衷是,如果变量a不存在就执行里边的语句,但如果a未定义,那么会报错,也不会执行里边的语句。
那么如何判断是否已经定义该对象呢?
一个比较巧妙的办法是:
[javascript]viewplaincopy
1.if(!
window.a){
2.//要执行的代码
3.}
这么写的确很巧妙,因为读取一个未定义的变量会报错,而读取一个未定义的属性却不会报错!
!
天晓得js为啥规定了这样的语法!
但这种方法仅适用于全局变量,如果是函数里的局部变量,还是用typeof去判断把:
[javascript]viewplaincopy
1.if(typeof a == "undefined"){
2. //相关操作
3.}
所以结论就是:
养成好习惯,不要在变量没有声明之前调用它。
接下来另外一个例子:
[javascript]viewplaincopy
1.var a = "I am out";
2.(function(){
3. alert(a);
4. var a = "I am in";
5.})()
好,提问,运行这段代码弹出什么?
回答1:
Iamout。
错,js没有块级作用域,无论var语句放在哪里,在整个函数体内他都是有定义的。
回答2:
Iamin。
错,再看上面那句话,它只是在整个函数体内有定义,但只有在被赋值后才有值。
正确答案:
undefined。
是不是很晕?
好好看看吧还是。
总之,再重复一遍,不要在变量声明之前调用它。
最后介绍一个我也没搞明白的问题:
在html文档里写如下这段代码:
[html]viewplaincopy
1.
4.
5.
然后呢,out.js里边这么写:
[javascript]viewplaincopy
1.if(false){
2. var a = "hello";
3.}
然后用FF跟IE6分别运行,看看得到什么。
FF中会弹出Hi,IE6会弹出undefined。
很神奇吧,按语法,无论如何a都不可能是undefined,但IE6会。
如果把这两个语句都写在同一个文件里,就不会有这个情况。
如果把out.js里的vara移到if语句外边,或者把if的条件改为true,也不会有这个问题。
这个bug的危害性其实非常大,所以呢,只能给自己定一个好习惯,那就是不要在条件语句中声明变量,虽然这么做语法上并不禁止。
注明:
1.作用域不同产生的效果也不一样,在同一个function中,js会先在function中查找是否有status的声明,如果有,则以function域中的为准,但是也有使用的先后顺序问题。
2.同时在同一作用域中变量的赋值的时候,函数的赋值要快于一般常量的赋值。
[javascript]viewplaincopy
1.如:
function b(){
2. alert(a);
3. var a = "常量";
4. function a(){}
5. }
alert的结果是functiona(){}
[javascript]viewplaincopy
1.如:
function b(){
2. alert(a);
3. var
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JS 执行 顺序
![提示](https://static.bdocx.com/images/bang_tan.gif)