zoukankan      html  css  js  c++  java
  • Javascript的"预编译"思考

    ref:http://eclipse07.iteye.com/blog/501169

    今天工作需要,搜索下JS面试题,看到一个题目,大约是这样的 

    Js代码  收藏代码
    1. <script>  
    2.    var x = 1, y = z = 0;  
    3.    function add(n) {  
    4.        n = n+1;  
    5.   }  
    6.   
    7.    y = add(x);  
    8.      
    9.    function add(n) {  
    10.       n = n + 3;  
    11.    }  
    12.   
    13.    z = add(x);  
    14. </script>  



    问执行完毕后 x, y, z 的值分别是多少? 

    仔细看的人马上就知道了, x, y 和 z 分别是 1, undefined 和 undefined。 

    不过,如果将两个 add 函数修改一下,题目变为 

    Js代码  收藏代码
    1. <script>  
    2.    var x = 1, y = z = 0;  
    3.    function add(n) {  
    4.       return n = n+1;  
    5.   }  
    6.   
    7.    y = add(x);  
    8.      
    9.    function add(n) {  
    10.       return n = n + 3;  
    11.    }  
    12.   
    13.    z = add(x);  
    14. </script>  


    那么这时 y 和 z 分别是什么呢?我马上想到是 2 和 4,不过结果却是 4 和 4。 
    这说明,在第一次调用 add 函数之前,第二个 add 函数已经覆盖了第一个 add 函数。原来,这是 JS 解释器的"预编译",JS 解析器在执行语句前会将函数声明和变量定义进行"预编译",而这个"预编译",并非一个页面一个页面地"预编译",而是一段一段地预编译,所谓的段就是一个 <script> 块。且看下面的代码 

    Js代码  收藏代码
    1. <script>  
    2.    function add(n) {  
    3.       return n = n+1;  
    4.   }  
    5.    alert(add(1));  
    6. </script>  
    7.   
    8. <script>  
    9.    function add(n) {  
    10.       return n = n+3;  
    11.   }  
    12.    alert(add(1));  
    13. </script>  



    会分别弹出 2 和 4。 

    那么,将上面的题目再变换一下,如下 

    Js代码  收藏代码
    1. <script type="text/JavaScript">  //第一段JavaScript代码
    2.    alert(typeof addA);  
    3.    addA();  
    4.    function addA() {  
    5.       alert("A executed!");  
    6.    };  
    7. </script>  
    8. <script language="JavaScript">    //第二段JavaScript代码
    9.    alert(typeof addB);  //undefined,说明addB是声明了的,但是没附初值
    10.    addB();  //如果在这调用函数addB() 会报错
    11.    var addB = function() {  
    12.      alert("B executed!");  
    13.    };  
    14.   addB();//B executed!  如果在此位置调用函数addB(),则不会报错
    15. </script>  

      解释 第二段JavaScript代码

    <script language="JavaScript">

          alert(typeof(a));     //undefined
          var a=5;
    </script>

    在执行第二段JavaScript代码的时候 ,首先会对这段代码进行预编译,然后再执行"var addB = function() {  }"  实际上就是 对一个变量addB的"预编译", 对一个变量的预编译的时候,并没有对该变量进行初始化(在执行该语句的时候才对变量进行初始化)。在执行"alert(typeof addB)"的时候,由于还没有对变量addB附初值,所以是undefined

    在预编译的时候把addB当成一个变量,在执行的时候把addB当成一个函数

    执行结果是什么呢? 按照前面的知识,第一个 <script> 块执行正常,结果就是弹出 "function" 和 "A executed!" 的对话框。 
    那么第二个 <script> 块呢? 执行结果是弹出 "undefined" 的对话框后报 JS 错误,说 addB 不是一个 function。 
    有点出乎意料?呵呵,其实第一个 script 块中的 addA 一句是函数声明,当然进行了"预编译",但是第二个 script 块中的 addB 一句并非函数声明。只不过在执行这段 <script> 之前对变量进行了"预声明",因此一开始变量addB是存在的,只不过是 undefined 的(可参看http://eclipse07.iteye.com/admin/blogs/484566)。因此执行结果便如上面所示。 

    将题目再变化下,如下 

    Js代码  收藏代码
    1. <script>  
    2.    alert(typeof addB);  
    3.    addB();  
    4.    var addB = function addB() {  
    5.      alert("B executed!");  
    6.    };  
    7. </script>  


    执行结果如何呢? 
    在 ff 下执行,与上面执行结果一样。打住,且在 IE6 下执行看看如何。 
    结果是弹出 "function" 和 "B executed!",一切正常。 
    Google 了一下,有人说这是 IE 的 BUG。 

    那么,请看下面的代码 

    Js代码  收藏代码
    1. <script>  
    2.    alert(typeof addB);  
    3.    var addB = "variable";  
    4.    function addB() {  
    5.        alert("function addB");  
    6.    }  
    7.    alert(addB);  
    8. </script>  


    执行结果是"function"和"variable"。 
    JS解析器先预定义了 addB 变量为 undefined, 但是 addB 函数覆盖了此变量,因此一开始执行结果是 function,然后 addB 被赋值为 "variable",因此最后执行结果是 "variable",上面的代码即使变为 

    Js代码  收藏代码
    1. <script>  
    2.    alert(typeof addB);  
    3.    function addB() {  
    4.        alert("function addB");  
    5.    }  
    6.    var addB = "variable";  
    7.    alert(addB);  
    8. </script>  


    结果也一样,这说明JS解析器先预声明变量,再预定义函数。 

    小结一下:JS 在执行前会进行类似"预编译"的操作,而且先预定义变量再预定义函数。

  • 相关阅读:
    面试准备
    论文投稿Cover letter
    Pycharm 快捷键
    linux下常用命令:
    Qt中数据模块学习
    Qt 多线程和网络编程学习
    VS高效开发快捷键
    良好编码风格习惯整理
    Qt QAxObject操作excel文件过程总结(转):
    Qt开发中的实用笔记三--关于各种类的零碎知识点:
  • 原文地址:https://www.cnblogs.com/SpringSmallGrass/p/3044569.html
Copyright © 2011-2022 走看看