美文网首页
JavaScript预编译与变量提升

JavaScript预编译与变量提升

作者: LeeYaMaster | 来源:发表于2019-05-30 20:07 被阅读0次

    去年,啃了很久很久的大犀牛(JS权威教程),啃得牙齿疼,今天重新回顾大犀牛,发现挺简单的,之前一直觉得难懂的变量提升,现在一眼就会了,于是便写下这篇博客,就当重新回顾一下了。
    JavaScript是一门解释型的语言 , 想要运行JavaScript代码需要两个阶段
    编译阶段: 编译阶段就是我们常说的JavaScript预解释(预处理)阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码
    执行阶段: 在编译阶段JavaScript解释器借助执行环境把字节码生成机械码,并从上到下按顺序执行
    栈内存:用来提供一个供JS代码执行的环境,即作用域(全局作用域/私有的作用域)
    堆内存:用来存储引用数据类型的值。对象存储的是属性名和属性值,函数存储的是代码字符串。

    什么是预编译?

    预解释:JavaScript代码执行之前,浏览器首先会默认的把所有带var和function的进行提前的声明或者定义
    1、变量的声明提前

      console.log(a);//undefined
      var a = 1;
    

    会编译成

      var a;
      console.log(a);
      a = 1;
    

    2、function的声明提前
    var =>在预解释的时候只是提前的声明
    function =>在预解释的时候提前的声明+定义都完成了
    for循环,也是函数作用域,if,switch不是。
    3、只会提前window作用域的变量,在函数里面的,只会调用的时候,再声明提前。

    实战篇

    第一弹:

    var a=1,b=2,c=3;
    function main(a){
        a = 4;
        var b = 5;
        c = 6;
    }
    main(6);
    console.log(a);console.log(b);console.log(c);//1,2,6
    a输出为6,是因为a是作为参数传进去,传到函数体,那么便是私有变量。
    b输出为2,是因为在函数里var b,重新定义,由于在函数体内,所以也是私有变量。
    c输出为6,是因为在函数里,他会去查找c,如果没有,往上一级一直查找,所以,会更改全局变量,输出为6
    

    第二弹:

    var num = 0;
    function main(num1,num2){
        console.log(num);//undefined
        var num = num1+ num2;
        console.log(num);//30
    }
    main(10,20);
    console.log(num);//0
    第一个为undefined是因为变量提升,var num;所以为undefined
    第二个输出30,是因为参数进去了,所以为30
    第三个为0,是因为在方法里,用了var,重新定义了一个局部变量,只是名字和全局变量一样而已,所以输出的时候,还是全局变量,所以为0
    

    第三弹:

                if(!"num" in window){
                    var num = 12;
                }
                console.log(num);//undefined
                原因在于变量提升,if不是函数作用域,所以var num会提升到最上面,所以也就成了全局作用域了。
    

    函数是一等公民:

    第四弹:

                function a(){}
                var a;
                console.log(typeof a);
                a();
                输出function,原因是因为函数会首先被提升
    

    第五弹:

                fn()
                var fn = function a(){
                    console.log("ok");
                }
                报错,fn is not a function,是因为函数提升,var fn = xxx ; "="后面的不会提升,只会提升前面部分。
    

    第六弹:

                var a = 1;
                function a(a){
                    console.log(a);
                    var a = 3;
                }
                a(2);
                报错,a is not a function。是因为函数声明,比变量声明优先级更高,并且把变量覆盖,但是变量可以重新定义,var a = 3;又把函数覆盖了。所以会输出不是一个函数。
    

    为了便于理解,函数会编译为:

                function a(a){
                    console.log(a);
                    var a = 3;
                }
                a = 1;
                a(2)
    

    第七弹:

    function a(){return true};
    console.log(a);
    console.log(a());
    第一个会输出整个函数字符串,第二个则会调用整个函数。这就是区别啦~
    function a(){}
    var a = function(){}
    两种写法都是一样的,只是一个是函数方式,一个是函数字面量方式。当然,这只在弱类型语言行得通~
    

    以上,便是预编译和变量提升的所有知识点啦~

    相关文章

      网友评论

          本文标题:JavaScript预编译与变量提升

          本文链接:https://www.haomeiwen.com/subject/yrfbtctx.html