• javascript练习题(2):变量作用域


    1. 外层变量在内部可以找到,反之找不到

    以下看个案例:

    var a=10;
    function aaa(){
        alert(a);
    }
    
    function bbb(){
        var a=20;
        aaa();
    }
    
    bbb();
    

    结果是?

    aaa()和外层的a=10处于同一个变量作用域。所以只能查找10.

    如果把a=10去掉呢?结果是报错了。

    还是变量作用域的问题,aaa的环境在全局环境下,不可能找到bbb里面的a=20.

    2. var的问题:不var就是全局变量

    var不写也是可以的。但是不写可能产生一些问题——变量会变成一个全局变量!

    由此衍生出这样的问题:

    function aaa(){
        var a=b=10;
    }
    aaa();
    alert(a);
    alert(b);
    

    回想问题,b变成了一个全局变量,a是一个局部变量。

    所以alert(a)会报错。

    去掉alert(a),aaa()运行的结果是产生了一个全局变量b和一个局部变量a。所以alert(b)的结果是10。

    3.变量查找是就近原则,寻找var定义的变量

    var a=10;
    function aaa(){
        alert(a);
        var a=20;
    }
    
    aaa();
    

    结果是什么?

    既不是10也不是20。是undefined

    当就近未找到,就会查找外层。一层一层知道直到找到为止。把结果简化一下吧:

    var a=10;
    function aaa(){
        var a=20;
        alert(a);   
    }
    
    aaa();
    

    结果是20。这很符合常识的推断。

    var a=10;
    function aaa(){
        a=20;
        alert(a);   
    }
    
    aaa();
    

    弹出a也是20,但是运行过程需要注意:最开始查找10,接着查找内部,发现a被修改为20.——本质是调用了外层的a。

    好了。现在回到本节最初的例子,aaa调用alert的时候,查找的是外层的a,这个进程遇到var a=20这一步时,由于函数内部预解析,查找的作用域就变了。开始查找函数内部的a,但是var a=20这一步放在了后面,所以结果是undefined。

    实际上代码变成了这样:

    var a=10;
    function aaa(){
      	var a;
        alert(a);
        a=20;
    }
    
    aaa();
    

    所以所有变量在定义时必须放最前面、

    4.结合分析

    var a=10;
    function aaa(){
        bbb();
        alert(a);
        function bbb(){
            var a=20;   
        }   
    }
    
    aaa();
    

    的结果是什么?

    弹出结果是10。因为a是局部中的局部,说白了找不着。

    那如果这么写呢?

    var a=10;
    function aaa(){
        bbb();
        alert(a);
        function bbb(){
            return a=20;   
        }   
    }
    
    aaa();
    

    好了。由于函数的预解析作用,导致bbb执行修改了全局变量a。所以弹出结果是20.同理,如果我把全局变量var a=10删去。结果还是20。因为bbb又创造了一个全局变量a。

    5. 参数跟局部变量同名,优先级是等同的

    var a=10;
    function aaa(a){
        alert(a);
    }
    
    aaa(a);
    
    

    这个简单的例子中弹出的是10。

    如果把参数改成b,

    var a=10;
    function aaa(b){
        alert(a);
    }
    
    aaa();
    

    结果还是10.

    那么这个a究竟是参数呢,还是全局变量a?

    答案是,参数名和全局变量名一样时,走的是参数,不一样时,走的是全局变量。

    比如:

    var a=10;
    function aaa(a){
      a+=3;
    }
    aaa(a);
    alert(a);//结果是10
    

    基本数据类型不存在引用关系,里面的a就是一个局部变量

    看个纠结一点点的吧:

    var a=5;
    var b=a;
    b+=3;
    
    alert(a)
    

    a是5。这是常识。

    基本类型的赋值是不存在引用关系的。但如果我想让a和b存在引用关系,应该怎么做?

    var a={
        a:5
    }
    var b=a;
    b.a+=3;
    console.log(a);//{a:8}
    

    如果不存在依存关系——

    var a={
        a:5
    }
    var b={
        a:a.a
    };
    b.a+=3;
    console.log(a);
    

    另外一个简单例子是数组。

    假设这样

    var a=[1,2,3];
    var b=a;
    
    b.push(4);
    console.log(a);//[1,2,3,4]
    

    所以真的要小心了。如果你不想存在引用关系,应该

    var b=a.slice()
    

    复合对象应用关系还可以衍生出这样的操作:

    var a=[1,2,3];
    
    function aaa(a){
        a.push(4);
    }
    aaa(a);
    console.log(a);//[1,2,3,4]
    

    真是没有做不到,只有想不到,这个a又是什么鬼?不是局部变量吗?

    a是确实是局部变量没错,但是它引用了外部的数组a。对这个局部变量的操作必将导致外部a的改变!

    下面的代码或许让人更清醒些——

    var a=[1,2,3];
    
    function aaa(a){
        a=[1,2,3,4]
    }
    aaa(a);
    console.log(a);//[1,2,3,4]
    

    因为参数a没有引用外部的a,所以怎么操作都跟外部的a没半毛钱关系!

  • 相关阅读:
    超神头文件
    世界上还有比二分更容易错的算法吗?
    【POJ 1734】Sightseeing trip
    P1303 A*B Problem
    P1601 A+B Problem(高精)
    P1051 谁拿了最多奖学金
    【P1025】数的划分
    P1005 矩阵取数游戏
    P1006 传纸条
    邮票问题
  • 原文地址:https://www.cnblogs.com/djtao/p/6265618.html
Copyright © 2020-2023  润新知