手记

Javascript全局变量和局部变量的陷阱


作用域是 JavaScript 最重要的概念之一,说简单也简单,说难也难。

下面是在学习的过程中总结出来的一点东西。


简单的说,作用域就是变量与函数的可访问范围。
JavaScript 中,变量的作用域有全局作用域和局部作用域两种。

要注意:

  • 全局变量的作用域是全局性的,即在整个 Javascript 程序中,全局变量作用处处都存在。定义在 "script" 块中,在 "function" 函数外。
  • 局部变量的作用域是局部性的,在函数内部或函数参数时定义,作用范围是从函数开始到结尾,即在{}里。

1. 全局变量

作用域的方式:

<script>
    var str1 = "hello1";        //定义一个全局变量,实际上是一个variable
    str2 = "hello2";            //定义一个全局变量,实际上是在global下创建一个property
    window.str3 = "hello3";     //定义一个全局变量
    function func(){
        var str4 = "hello4";    //定义一个局部变量
        str5 = "hello5";        //定义一个全局变量
    }
</script>

for in window 判断是否是全局变量

    function Write(str){    //封装了 document.write(); 
        document.write(str + '<br />');
    }

    for(w in window){
        if(w == 'str1' || w =='str2' || w == 'str3' || w == 'str4' || w == 'str5'){
            Write(w);
        }
    }

由此说明,定义全局变量的几种方式,还是有点区别的,它们会因游览器内核不同,而被识别为全局变量也不同。


2. 全局变量的问题

Javascript总是在不知不觉中就出人意料地创建了全局变量。就像:

    function func(){
        var a = b = 0;
        //. . .
    }

在这里,你可能想定义两个局部变量,但是代码却是 a 是局部变量,b 是全局变量。原因很简单,由于操作符的优先级是从右到左的,就像。

    var  a = ( b = 0 );

改为:

    var a, b;
    a = b = 0;

如果对链式赋值所有变量都进行了声明,就不会创建出不期待的全局变量。


3. 局部变量的问题
先来看看,下面的代码:

<script>
    var str = "我是妹子";
    (function func(){
        var str = "我不是妹子";
        Write(str);
    })();
    Write(str);
</script>

可以看出:

  • 在函数内部,局部变量的优先级比同名的全局变量优先级要高;
  • 如果存在与全局变量名称相同的局部变量(包括参数),那么该全局变量将不再起作用。
  • 局部变量的生存域仅在函数体里,出了函数体,它就不存在了。
    就像:
<script>
    (function func(){
        var str = "我不是妹子";  
        Write(str);
    })();
    Write(str); 
</script>


第二句 Write(str); 没有东西输出。


4. 变量释放时的问题

先来看看,下面的代码:

<script>
    var a = 1;          //全局变量
    window.b = 2;       //全局变量
    delete a;
    delete b;
    Write(typeof a);
    Write(typeof b);
    (function func(){
        var c = 3;      //局部变量
        d = 4;          //全局变量
        delete c;
        delete d;
        Write(typeof c);
        Write(typeof d);
    })();
</script>


可以看出:

  • 使用 var 创建的变量不能使用 delete 释放内存。
  • 不使用 var 创建的变量可以使用 delete 释放内存。

5. 零散变量的问题

Javascript允许在函数的任意地方声明多个变量,无论在哪里声明,效果都等同于在函数顶部进行声明。就像:

<script>
    var str = "我是妹子";
    (function func(){
        Write(str);
        var str = "我不是妹子";
        Write(str);
    })();
</script>

为什么不是: 我是妹子 和 我不是妹子?
原因很简单:对JavaScript而言,只要变量是在同一个范围(函数)里,就视为已经声明,哪怕是在变量声明前就使用。上面的代码相当于:

<script>
    var str = "我是妹子";
    (function func(){
        var str;    //系统自动赋值为 str = undefined
        Write(str);
        var str = "我不是妹子";
        Write(str);
    })();
</script>

总的来说:
1. 要清楚在哪个地方声明定义的是 全局变量 还是 局部变量
2. 全局变量所带来的 bug 问题非常多,可能很偶然的把代码放到其他页面里,把新页面的同名变量给覆盖,造成隐藏的 bug 。最好尽量少用全局变量。
3. 不应使用带 var 的链式赋值,声明变量最好带 var
4. 在函数体内定义变量时,最好把变量放在顶部。为了防止出现变量在定义前就被使用的逻辑错误。

29人推荐
随时随地看视频
慕课网APP

热门评论

谢谢楼主分享,辛苦了!

楼主。 班门弄斧。

查看全部评论