涉及到JavaScript运行机制和函数的作用域去深入了解变量。

全局变量与局部变量

首先要了解变量的生存期:

全局变量:从定义开始一直到本程序结束为止。
局部变量:在函数中定义,有效范围在函数之内,当函数结束后,局部变量生存期也就结束了。

有一点时:当给未声明的变量赋值,JavaScript 会自动用该变量名创建一个全局变量。
ps 一个小例子

<script>
    function a(){
        i=1;
    }
    function b(){
        alert(i);
    }
    b();
</script>

执行结果 i is not defined
解释:函数 a 没有被调用,相当于声明了 i ,但是没有给 i 赋予任何值。这里 i 为全局变量。

JS的解析过程分为两个阶段:预编译期(预处理)与执行期

预编译期:对所有声明的变量和函数进行处理。声明的函数前置;变量进行声明但未进行初始化(即只是分配了内存)即:
变量:查找通过var 声明的变量,马上作为window一个属性并初始化为 undefined
函数:声明的函数前置

以下为两个例子:

<script>
    alert(a);
    var a = 1 ;
</script>

结果输出 undefined

<script>
    alert(a);
    a = 1 ;
</script>

结果 报错,a is not defined。这段代码被解析时并未发现有var关键字,因此执行到alert(a)时,就等于执行alert(window.a),而window对象尚没有a属性,当然就报错了。

在看个案例

<script>
    var a = 10;
        var b = true;

        function test() {
            alert(a);        //undefined
            alert(b);        //true
            var a = 200;
            b = false;
            alert(b);        //false
            alert(a / 2);    //100
        }
        test();
        alert(a);            //10
        alert(b);            //false
</script>

执行过程
首先,js 要预编译,预编译过程中为每个变量分配了内存。

javascript局部变量全局变量 js局部变量和全局变量_javascript局部变量全局变量

第二步,按照代码的顺序执行代码:

var a = 10:为全局变量a 赋值
var b = true:为全局变量 b 赋值
test(){}:进入函数test ,则由于局部变量会在函数内部覆盖同名的全局变量,故此时的状态便是a 未赋值,b的值为true
var a = 200: 将位于函数test 中的局部变量a 赋值200,覆盖同名的全局变量
b = false:将位于函数test中的全局变量b 赋值false,覆盖同名的全局变量
test{} 函数执行结束:局部变量a 生存期结束,全局变量 b 值为 false

解释函数内部 alert(a) 为什么值为 undefined

预编译阶段:获得已声明的变量a、b 和声明函数test 作用域以及函数内部 a的作用域。
程序执行到第六行代码时:立即调用内围作用域的a,这时它还没有来得及赋值呢!不过它已经声明过了,因此默认为其赋值为 undefined(在预编译阶段,见图),于是 alert 为 undefined。
程序执行到第七行代码时:就调用 b 时,发现 test 的作用域内没有 b,则往外寻,于是 alert 为 true。