alert(a);
    var a = 1;
    function a(){
    alert(2);
    }
    alert(a);
    var a = 3;
    alert(a);
    function a(){
    alert(4);
    }
    alert(a);
    js解析器的执行原理 - 图1
    上面代码的执行顺序是从上往下,当代码执行到script标签时,开始执行js代码。
    执行js代码一般分两步:1.预解析代码。 2.逐行执行代码。
    第一步:预解析代码
    预解析代码,主要会把var , function , 参数等一些东西存储进仓库里面(内存)。
    1.var 一般用于声明变量,预解析代码时,等号后面的赋值过程不会执行,所以预解析时的var 变量 都是未定义的。
    2,.function 函数,预解析时,值就是函数里面的内容。
    当变量和函数重名时:就只留下函数的值,不管顺序谁前谁后。所以函数的优先级比变量高(注意:这只是预解析)。
    当函数和函数重名时:会留下后面那个,会遵循上下文机制。
    第二步:逐行执行代码
    当预解析完成后,开始逐行执行代码,全部代码都会完整的执行。
    // alert 弹出何值?
    js解析器的执行原理 - 图2
    alert(a);
    var a=1;
    function a(){
    alert(2);
    }
    alert(a);
    var a=3;
    alert(a);
    function a(){
    alert(4);
    }
    alert(a);
    js解析器的执行原理 - 图3
    第一步:预解析
    上面说过,预解析时只会把var , function ,参数等存储起来,所以:
    执行到第二行时,a 的值是未定义。
    执行到第四行时,a 的值是函数本身,也就是function a(){alert(2);}。
    执行到第六行时,a 的值还是第四行时的值,也就是function a(){alert(2);},因为函数的优先级比变量高。
    执行到第八行时,a 的值就变成了function a(){alert(4);} ,因为当两个函数重名时,遵循代码从上往下执行。
    第二步:代码逐行执行
    预解析完成之后,就是代码逐行执行了,
    第二行:会弹出function a(){alert(4);} ,因为预解析完成之后,被存进内存的a 的值就是function a(){alert(4);}
    第三行:第三行里有表达式,a 被赋了一个新的值1 表达式会改变变量的值。表达式可以改变预解析的值。
    第四行:只是函数的声明,并没有用到表达式,而且也没有函数的调用,所以不会改变a 的值。
    第五行:因为a 的值没有变化,所以还是1
    第六行:使用了表达式,a 被赋了一个新的值3
    第七行:会弹出3
    第八行:函数的声明,不会改变a 的值。
    第九行:a的值没有改变,所以还是3
    js解析器的执行原理 - 图4
    // 输入
    alert(a); // 弹出function a(){alert(4)}

    var a=1;
    function a(){
    alert(2);
    }
    alert(a); // 弹出1
    var a=3;
    alert(a); // 弹出3
    function a(){
    alert(4);
    }
    alert(a); // 弹出3
    js解析器的执行原理 - 图5
    闭包的定义:函数内部形成的私有作用域保护了内部变量,使得外部无法改变内部变量,内部变量也无法改变外部的同名变量,这种机制叫做闭包