近期在学习js,了解到js的一个名词,就是hoisting,进而了解了下js的解析机制
详情可参考:http://www.runoob.com/js/js-hoisting.html
js的解析过程分为两个阶段:编译阶段和执行阶段
编译阶段:即我们常说的预处理阶段,javascript解析器把js脚本代码转换为字节码
在这个阶段,解析器所做的事有:
将所有变量和函数进行预处理,hoisting就是在这个时候发生的。
提升原则:
1.函数优先于变量,即函数提升完之后,才会处理变量的声明,
2.对于已经初始化的变量(var a=2;)是不会提升的,
3.使用表达式定义函数(eg:var a =function(){console.log();})是无法提升的。
例如:
<script>
 function func(){  //函数声明和函数表达式的区别
     alert(" a:"+a());
     alert("b="+b);
     var a=1;
     var b;
     b=2;
     alert("b="+b);
     function a()
     {
         alert("this is function a");
         return "this is a return a";
     }
     alert( "a:"+a);           
 }
 func();
 </script>
 //输出结果:
 this is function a
 a:this is a return a
 b=undefined
 b=2
 a=1
 提升(hoisting)后:
<script>
 function func(){  //函数声明和函数表达式的区别
     function a()//函数声明提升
     {
         alert("this is function a");
         return "this is a return a";
     }
     var b;//未初始化的变量,提升,后于函数
     alert(" a:"+a());
     alert("b="+b);
     var a=1;//对于已经初始化的变量,则不提升
     b=2;
     alert("b="+b);
     alert( "a:"+a);           
 }
 func();
 </script>
 函数的提升:
<script>
     try
     {
         
         a();
         function a()
         {
             alert("this is function a");
         }
         alert(b);
         b();//出错位置
         var b=function(){
             alert("this is function b");
         }
         b();
     }catch(e)
     {
         alert(e);
     }
 </script>
 //输出结果
 //this is a function a
 //undefined
 //TypeError: b is not a function
 //提升之后的结果:
 <script>
     try
     {
         function a()//常规函数提升
         {
             alert("this is function a");
         }
         var b;//表达式函数提升
         a();
         alert(b);//b未定义
         b();//b未定义,不是函数,报错
         b=function(){
             alert("this is function b");
         }//变量定义
         b();
     }catch(e)
     {
         alert(e);
     }
 </script>
 执行阶段:将字节码生成机械码并按顺序执行。
JS代码是按块被引擎预编译和解释执行的,所谓块就是<script>标签分割的代码段。
注意:JS是按块被引擎预编译和解释执行的,一对<script></script>标签表示一个执行块,因此在当前块中调用下一个块中声明定义的变量和函数会报语法错误。
虽然js是按照块执行的,但是因为所有块同属于同一个全局作用域,即块之间的变量和函数是可以共享的。
因此我们可以借助事件机制,来改变执行顺序。
当文档流完全被加载完毕,再次访问就不会出现语法错误,比如将访问第二个代码块中的变量和函数的代码放在页面初始化事件函数中,就不会提示语法错误。、
   
<script>
     window.onload = function() { //页面初始化(加载)完毕之后才执行页面初始化事件处理函数
         alert(a);
         f();
     }
 </script>
     
 <script>
         var a = 1;
         function f() {
             alert(a+a);
         }
 </script>
    //除了页面初始化事件外,还可以通过各种交互事件如鼠标事件、键盘事件、时钟触发等改变JS代码执行顺序。
  
JS提升(hoisting)详解_mao_mao37的博客-CSDN博客