zoukankan      html  css  js  c++  java
  • js基础(1)变量作用域

    在JavaScript中,用var申明的变量实际上是有作用域的。

    如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量:

    'use strict';
    
    function foo() {
        var x = 1;
        x = x + 1;
    }
    
    x = x + 2; // ReferenceError! 无法在函数体外引用变量x
    

    如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响:

    'use strict';
    
    function foo() {
        var x = 1;
        x = x + 1;
    }
    
    function bar() {
        var x = 'A';
        x = x + 'B';
    }
    

    由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:

    'use strict';
    
    function foo() {
        var x = 1;
        function bar() {
            var y = x + 1; // bar可以访问foo的变量x!
        }
        var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!
    }
    

    如果内部函数和外部函数的变量名重名怎么办?

    'use strict';
    
    function foo() {
        var x = 1;
        function bar() {
            var x = 'A';
            alert('x in bar() = ' + x); // 'A'
        }
        alert('x in foo() = ' + x); // 1
        bar();
    }
    

    这说明JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。

    变量提升

    JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:

    'use strict';
    
    function foo() {
        var x = 'Hello, ' + y;
        alert(x);
        var y = 'Bob';
    }
    
    foo();
    

    虽然是strict模式,但语句var x = 'Hello, ' + y;并不报错,原因是变量y在稍后申明了。但是alert显示Hello, undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。

    对于上述foo()函数,JavaScript引擎看到的代码相当于:

    function foo() {
        var y; // 提升变量y的申明
        var x = 'Hello, ' + y;
        alert(x);
        y = 'Bob';
    }
    

    由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量:

    function foo() {
        var
            x = 1, // x初始化为1
            y = x + 1, // y初始化为2
            z, i; // z和i为undefined
        // 其他语句:
        for (i=0; i<100; i++) {
            ...
        }
    }
    

    全局作用域

    不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性:

    'use strict';
    
    var course = 'Learn JavaScript';
    alert(course); // 'Learn JavaScript'
    alert(window.course); // 'Learn JavaScript'
    

    因此,直接访问全局变量course和访问window.course是完全一样的。

    你可能猜到了,由于函数定义有两种方式,以变量方式var foo = function () {}定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window对象:

    'use strict';
    
    function foo() {
        alert('foo');
    }
    
    foo(); // 直接调用foo()
    window.foo(); // 通过window.foo()调用
    

    进一步大胆地猜测,我们每次直接调用的alert()函数其实也是window的一个变量:

  • 相关阅读:
    禁止页面缓存 移动端
    常见的请求头与响应头介绍
    阮一峰 ES6学习
    禁止页面缩放 移动端
    10月30日学习日志
    11月7日学习日志
    11月6日学习日志
    10月31日学习日志
    11月1日学习日志
    11月9日学习日志
  • 原文地址:https://www.cnblogs.com/zzlm/p/7049213.html
Copyright © 2011-2022 走看看