代码改变世界

转:JavaScript预编译与执行顺序的关系

2013-03-08 21:42  youxin  阅读(246)  评论(0编辑  收藏  举报

首先关于函数的:

在Javascript中,function才是Javascript的第一型。当我们写下一段函数时,其实不过是建立了一个function类型的实体。

就像我们可以写成这样的形式一样:

function Hello() {
            alert("Hello");
        }
        Hello();
        var Hello = function () {
            alert("Hello");
        }
        Hello();

 

其实都是一样的。

但是当我们对其中的函数进行修改时,会发现很奇怪的问题。

    <script type="text/javascript">
        function Hello() {
            alert("Hello");
        }
        Hello();
        function Hello() {
            alert("Hello World");
        }
        Hello();
    </script>

 

我们会看到这样的结果:连续输出了两次Hello World。而非我们想象中的Hello和Hello World。

这是因为Javascript并非完全的按顺序解释执行,而是在解释之前会对Javascript进行一次“预编译”,在预编译的过程中,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率。也就是说上面的一段代码其实被JS引擎预编译为这样的形式:

    <script type="text/javascript">
        var Hello = function() {
            alert("Hello");
        }
        Hello = function() {
            alert("Hello World");
        }
        Hello();
        Hello();
    </script>

 

我们可以通过上面的代码很清晰地看到,其实函数也是数据,也是变量,我们也可以对“函数“进行赋值(重赋值)。当然,我们为了防止这样的情况,也可以这样:

 

    <script type="text/javascript">
        function Hello() {
            alert("Hello");
        }
        Hello();
    </script>
    <script type="text/javascript">
        function Hello() {
            alert("Hello World");
        }
        Hello();
    </script>

 

这样,程序被分成了两段,JS引擎也就不会把他们放到一起

 

 JS在执行每一段JS代码..

 

  1. <script>
  2.      alert(typeof eve); //结果:undefined
  3. </script>
  4. <script>
  5.      function eve() {
  6.           alert('I am Laruence');
  7.      }
  8. </script>

 

JS的预编译是以段为处理单元的

了。http://www.cnblogs.com/kym/archive/2010/01/06/1640030.html

 

 

对于函数的定义,是一个要注意的地方:

 

  1. <script>
  2.      alert(typeof eve); //结果:function
  3.      alert(typeof walle); //结果:undefined脚本报错
  4.      function eve() { //函数定义式
  5.           alert('I am Laruence');
  6.      };
  7.      var walle = function() { //函数表达式
  8.      }
  9.      alert(typeof walle); //结果:function
  10. </script>

 

这就是函数定义式和函数表达式的不同, 对于函数定义式, 会将函数定义提前. 而函数表达式, 会在执行过程中才计算.

当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。 
做如下处理: 
1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。 
2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 
所以,就会出现当JavaScript解释器执行下面脚本时不会报错: 

 
  1. alert(a);    // 返回值undefined  
  2. var a =1;  
  3. alert(a);    // 返回值1  


由于变量声明是在预编译期被处理的,所以在执行期间对于所有代码来说,都是可见的。但是,你也会看到,执行上面代码,提示的值是undefined,而不是1。这是因为,变量初始化过程发生在执行期,而不是预编译期。在执行期,JavaScript解释器是按着代码先后顺序进行解析的,如果在前面代码行中没有为变量赋值,则JavaScript解释器会使用默认值undefined。由于在第二行中为变量a赋值了,所以在第三行代码中会提示变量a的值为1,而不是undefined。