最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题

 


  代码:


 


复制代码


代码一

< 
 html> 

 

    <head> 

 

      <title>事件处理</title> 

 

      <meta http-equiv="content-type" content="text/html;charset=utf-8"/> 

 

      <script type='text/javascript'> 

 

          //页面在在完成加载后 

 

          window.οnlοad=function(){ 

 

              var input=document.getElementById('button'); 

 

              var p=document.getElementById('p'); 

 

              var i=1; 

 

              while(input){ 

 

                  input.οnclick=function(){ 

 

                      p.innerHTML+='<br />('+ i +') '+this.nodeName; 

 

                  } 

 

                  i++; 

 

                  input=input.parentNode; 

 

              } 

 

          } 

 

      </script> 

 

    </head> 

 

    <body> 

 

      <div> 

 

      <input type='button' value='Event事件' id='button' /> 

 

      <p id='p'>事件捕获的顺序:</p> 

 

      </div> 

 

    </body> 

 

  </html>

复制代码


 显示的结果为:


 


                      


 


当我更改了代码中红色的部分后得到的结果又不相同:


 


复制代码


代码二


<html> 

 

    <head> 

 

      <title>事件处理</title> 

 

      <meta http-equiv="content-type" content="text/html;charset=utf-8"/> 

 

      <script type='text/javascript'> 

 

          //页面在在完成加载后 

 

          window.οnlοad=function(){ 

 

              var input=document.getElementById('button'); 

 

              var p=document.getElementById('p'); 

 

              var i=1; 

 

              while(input){ 

 

                  input.οnclick=function(){ 

 

                      p.innerHTML+='<br />('+ i++ +') '+this.nodeName; 

 

                  } 

 

                  input=input.parentNode; 

 

              } 

 

          } 

 

      </script> 

 

    </head> 

 

    <body> 

 

      <div> 

 

      <input type='button' value='Event事件' id='button' /> 

 

      <p id='p'>事件捕获的顺序:</p> 

 

      </div> 

 

    </body> 

 

  </html>

复制代码


得到的结果为:


 


             


 


  得出这两种不同的结果那是因为javascript代码在运行时有预编译和执行两个阶段,在预编译阶段会对函数和变量进行处理,对所有的声明变量会赋值为underfined,对所有的声明函数也会赋值为函数的定义。


 


  下面我们来测试javascript的执行过程


 


  1.javascript代码执行顺序时按照脚本标签<script>出现的顺序来确定的,浏览下面页面你会发现代码是按从上到下的顺序执行的


 


复制代码


<script type='text/javascript'> 

 

      alert('one'); 

 

    </script> 

 

    <script type='text/javascript'> 

 

    alert('two'); 

 

    </script> 

 

    <script type='text/javascript'> 

 

    alert('three'); 

 

    </script>


复制代码


   2. 因为变量在预编译时被赋予一个undefined初值,所以下面代码中,第一个变量name在代码中没有被赋值,所有就延用undefined这个值,下面的name被赋予了Jude,所以第二次输出的是Jude这个字符。


 


<script type='text/javascript'>

alert(name);                    //显示undefined 

 

      var name='Jude'; 

 

      alert(name);                    //显示Jude 

 

  </script>


  3.从如下结果中我们知道先是连续两次输出Hello Wrold!,最后连续两次输出test,得出这样的结果是因为javascript并非是完全按照顺序执行的,而是在执行之前先进行一个预编译,预编译时声明式函数被提取出来,优先执行,而且相同的函数会进行覆盖,再执行赋值式函数。


 


复制代码


<script type='text/javascript'> 

 

      test();                    //输出Hello World! 

 

      function test(){        

 

          alert('hello');     //声明式函数 

 

      } 

 

      test();                    //输出Hello World! 

 

    

 

      var test=function(){    //赋值式函数 

 

          alert('test'); 

 

      } 

 

      test();                    //输出test 

 

      function test(){      //声明式函数 

 

          alert('Hello World!'); 

 

      } 

 

      test();                    //输出test 

 

  </script>


复制代码


  4.下面代码显示显示hello,再显示hello world!,这是因为javascript中的给个代码块是相互独立的,当脚本遇到第一个<script>标签时,则javascript解析器会等这个代码块加载完成后,先对它进行预编译,然后再执行之,然后javascript解析器准备解析下一个代码块,由于javascript是按块执行的,所有一个javascript调用下一个块的函数或者变量时,会出现错误


 


复制代码


<script type='text/javascript'> 

 

      function test(){ 

 

          alert('hello');                //显示hello 

 

      } 

 

      test() 

 

  </script> 

 

  <script type='text/javascript'> 

 

      function test(){ 

 

          alert('hello world!');        //显示hello world! 

 

      } 

 

      test() 

 

  </script>


复制代码


  5.虽然javascript是按块执行的,但不同的块却属于相同的全局作用域,不同的块的变量和函数式可以相互使用的,也就是某个块可以使用前面块的变量和函数,却不可以使用它之后的块的变量和函数


 


复制代码


<script type='text/javascript'> 

 

      alert(name);                    //显示undefined 

 

      var name='Jude'; 

 

      function test(){ 

 

          alert('hello'); 

 

      } 

 

      fun();                            //不能调用下一个块的函数 

 

  </script> 

 

  <script type='text/javascript'> 

 

      alert(name);                    //可以调用上一个块的变量,显示Jude 

 

      test();                            //可以调用上一个块的函数,显示hello 

 

      function fun(){ 

 

          alert('fun'); 

 

      } 

 

  </script>


复制代码


  6.javascript在预编译阶段是以函数来划分作用域的,然后再通过var 声明的变量来与声明函数开辟内存空间,对var变量赋初值undefined。在执行阶段再根据作用域来嘴变量进行赋值.


 


  第一个代码块中函数里面的变量a是局部变量,因为a在函数内重新用var定义,所以输出undefined,而变量b是全局变量,因为在函数内没有用var重新声明b,所以在给变量b赋值时到全局变量中找全局变量b的值,所以输出的是b.


 


  第二个代码块中的函数内都重新声明了变量a和b,所以他们都是函数内的局部变量,所以都输出undefined。


 


复制代码


<script type='text/javascript'> 

 

      var a='a'; 

 

      var b='b'; 

 

      function test(){ 

 

          alert(a);                //显示undefined 

 

          alert(b);                //显示b 

 

          var a='test'; 

 

      } 

 

      test(); 

 

  </script> 

 

  <script type='text/javascript'> 

 

      var a='a';                     

 

      var b='b';                     

 

      function test(){ 

 

          alert(a);                //显示undefined 

 

          alert(b);                //显示undefined 

 

          var a='test'; 

 

          var b='test'; 

 

      } 

 

      test(); 

 

  </script>


复制代码


  综上所述,javascript在执行时的步骤是:


 


    1、先读入第一段代码块


 


    2、对代码块进行语法分析,如果出现语法错误,直接执行第5步骤


 


    3、对var变量和function定义的函数进行“预编译处理”(赋值式函数是不会进行预编译处理的)


 


    4、执行代码块,有错则报错


 


    5、如果还有下一段代码块,则读入下一段代码块,重复步骤2


 


    6、结束