zoukankan      html  css  js  c++  java
  • JavaScript的变量作用域深入理解

    在学习JavaScript的变量作用域之前,我们应当明确几点:
    a、JavaScript的变量作用域是基于其特有的作用域链的。
    b、JavaScript没有块级作用域。
    c、函数中声明的变量在整个函数中都有定义。

    <script>
    var x = 1;
    function outer() {
        var y = 2;
        function inner() {
            var z = 4;
            alert(x);
        }
        inner(); 
    }
    outer(); 
    </script>

    alert(x)这句代码,JavaScript首先在inner函数中查找是否定义了变量x,如果定义了则使用inner函数中的x变量;
    如果inner函数中没有定义x变量,JavaScript则会继续在rainman函数中查找是否定义了x变量,在这段代码中outer函数体内没有定义x变量,则JavaScript引擎会继续向上(全局对象)查找是否定义了x;
    在全局对象中我们定义了x = 1,因此最终结果会弹出'1'。
    作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。
    上面的代码涉及到了三个作用域链对象,依次是:inner、outer、window。

    2、函数体内部,局部变量的优先级比同名的全局变量高。

    <script>
    var x = 1;
    function check() {
        var x = 100; //定义局部变量x
        alert(x); //这里会弹出 100
    }
    check();
    alert(x); //这里会弹出1
    </script>

    3、JavaScript没有块级作用域。
    这一点也是JavaScript相比其它语言较灵活的部分。
    仔细观察下面的代码,你会发现变量a、b、c作用域是相同的,他们在整个inner函数体内都是全局的。

    <script>
    function inner() {
        var a = 0;
        if (1) {
            var b = 0;
            for (var c = 0; c < 3; c++) {
                alert(c); // 分别弹出 0 1 2
            }
            alert(c); //弹出3 
        }
        alert(a); //弹出0
        alert(c); //弹出3 
    }
    inner();
    alert(c); //不弹值 ,如果将var c = 0 中 var 去掉,则会弹出 3
    </script>

    对于有块级作用域的语言来说,for语句中定义并初始化的变量i在循环外是无法访问的,而在javascript中,for语句中定义的变量c在循环结束后,依旧会存在于循环外部的执行环境(作用域)中,在这里c的作用域是全局环境。具体来说就是:使用var关键字声明变量时,这个变量会自动添加到距离最近的可用环境中。对于函数而言,这个最近的环境就是函数的局部环境。
    如果变量在未经声明的情况下被初始化,则该变量会被自动添加到全局环境。
    不过有时候的确很需要块级作用域来解决一些问题,这时候我们就可以使用匿名函数来模仿块级作用域。
    匿名函数就是没有名字的函数,有时候也被称为拉姆达(lamda)函数。形式如下:
    (function(){
    //块级作用域
    })();
    以上代码的意思是:首先定义并立即调用一个匿名函数。将函数声明包含在圆括号中,表示它实际上是一个函数表达式。而紧随其后的另一对圆括号表示立即调用这个函数。
    当匿名函数执行完毕,其作用域链立即销毁,从而可以减少闭包占用资源问题。

    4、函数中声明的变量在整个函数中都有定义。 

    <script>
    function outer() {
        var x = 1;
        function inner() {
            x = 100;
        }
        inner(); 
        alert(x); //弹出 100
    }
    outer(); 
    </script>

    上面代码说明了,变量 x 在整个 outer 函数体内都可以使用,并可以重新赋值。
    由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

    <script> 
    var x = 1;
    function inner() {
        alert(x); //弹出 'undefined',而不是1
        var x = 2;
        alert(x); //弹出 2
    }
    inner();
    </script> 

    这是由于在函数 inner 内局部变量 x 在整个函数体内都有定义 var x= 2,进行了声明 ) , 所以在整个 inner 函数体内隐藏了同名的全局变量 x 。
    这里之所以会弹出 'undefined' 是因为,第一个执行 alert(x) 时,局部变量 x 仍未被初始化。

    所以上面的 inner 函数等同于下面的函数。 

    <script> 
    function inner() {
        var x;
        alert(x);
        x = 2;
        alert(x);
    }
    </script> 

    5、未使用var关键字定义的变量都是全局变量。
    这也是JavaScript新手常见的错误,无意之中留下的许多全局变量。

    <script> 
    function inner() {
        x = 100; // 声明了全局变量x并进行赋值
    }
    inner();
    alert(x); //会弹出100
    </script> 

    6、全局变量都是window对象的属性 

    <script> 
    var x = 100;
    alert(window.x); //弹出100
    alert(x);
    </script> 

    等同于下面的代码 

    <script> 
    window.x = 100; 
    alert( window.x ); 
    alert(x) 
    </script> 
  • 相关阅读:
    人月神话阅读笔记03
    学习进度十六
    计算最长英语链
    学习进度十五
    人月神话阅读笔记02
    找“水王”
    学习进度十四
    用户体验评价
    学习进度十三
    学习进度十二
  • 原文地址:https://www.cnblogs.com/bigdesign/p/3999747.html
Copyright © 2011-2022 走看看