协慌网

登录 贡献 社区

JavaScript 中的变量范围是什么?

javascript 中变量的范围是什么?它们的内部是否与函数外部相同?或者甚至重要吗?此外,如果全局定义变量,那么它们存储在哪里?

答案

我认为我能做的最好的事情就是给你一些学习的例子。 Javascript 程序员实际上根据他们理解范围的程度进行排名。它有时可能非常违反直觉。

  1. 全局范围的变量

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
  2. 本地范围

    // global scope
    var a = 1;
    
    function two(a) { // passing (a) makes it local scope
      alert(a); // alerts the given argument, not the global value of '1'
    }
    
    // local scope again
    function three() {
      var a = 3;
      alert(a); // alerts '3'
    }
  3. 中间体没有这样的东西在 JavaScript 块范围 (ES5; ES6 介绍let

    一个。

    var a = 1;
    
    function four() {
      if (true) {
        var a = 4;
      }
    
      alert(a); // alerts '4', not the global value of '1'
    }

    var a = 1;
    
    function one() {
      if (true) {
        let a = 4;
      }
    
      alert(a); // alerts '1' because the 'let' keyword uses block scoping
    }
  4. 中级对象属性

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
  5. 高级关闭

    var a = 1;
    
    var six = (function() {
      var a = 6;
    
      return function() {
        // JavaScript "closure" means I have access to 'a' in here,
        // because it is defined in the function in which I was defined.
        alert(a); // alerts '6'
      };
    })();
  6. 高级基于原型的范围解析

    var a = 1;
    
    function seven() {
      this.a = 7;
    }
    
    // [object].prototype.property loses to
    // [object].property in the lookup chain. For example...
    
    // Won't get reached, because 'a' is set in the constructor above.
    seven.prototype.a = -1;
    
    // Will get reached, even though 'b' is NOT set in the constructor.
    seven.prototype.b = 8;
    
    alert(new seven().a); // alerts '7'
    alert(new seven().b); // alerts '8'

  7. 全球 + 本地一个额外复杂的案例

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();

    这将打印出undefined10而不是510因为 JavaScript 总是将变量声明(而不是初始化)移动到作用域的顶部,使代码等效于:

    var x = 5;
    
    (function () {
        var x;
        console.log(x);
        x = 10;
        console.log(x); 
    })();
  8. Catch 子句范围的变量

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);

    这将打印出565 。在 catch 子句中, e阴影全局变量和局部变量。但是这个特殊范围仅适用于捕获的变量。如果你写var f;在 catch 子句中,它与在 try-catch 块之前或之后定义它完全相同。

Javascript 使用范围链来为给定函数建立范围。通常有一个全局范围,每个定义的函数都有自己的嵌套范围。在另一个函数中定义的任何函数都有一个链接到外部函数的局部作用域。始终是源中定义范围的位置。

范围链中的元素基本上是一个带有指向其父范围的指针的 Map。

解析变量时,javascript 从最里面的范围开始并向外搜索。

全球声明的变量具有全局范围。在函数内声明的变量作用于该函数,并且阴影全局变量具有相同名称。

(我确信真正的 JavaScript 程序员可以在其他答案中指出很多细微之处。特别是我在这个页面上看到了this在任何时候this意味着什么。希望这个更多的介绍性链接足以让你开始虽然。)