【问题标题】:Are variables statically or dynamically "scoped" in javascript?javascript中的变量是静态还是动态“作用域”?
【发布时间】:2009-06-06 04:16:18
【问题描述】:

或者更具体到我需要的东西:

如果我从另一个函数中调用一个函数,它是从调用函数中还是从上面的级别中提取变量?例如:

myVar=0;

function runMe(){
    myVar = 10;
    callMe();
}

function callMe(){
   addMe = myVar+10;
}

如果通过 runMe() 调用 callMe(),myVar 最终会是什么?

【问题讨论】:

  • 你为什么不运行它并找出答案?
  • 把问题记录下来让其他人也能看到不是更好吗?
  • 答案实际上是开始理解词法与动态范围恕我直言的好方法,所以这很好听,但 Sasha 提醒初学者运行和试验总是一个好方法并没有错政策。

标签: javascript scoping


【解决方案1】:

杰夫是对的。请注意,这实际上并不是对静态范围(JS 确实有)的一个很好的测试。更好的是:

myVar=0;

function runMe(){
    var myVar = 10;
    callMe();
}

function callMe(){
   addMe = myVar+10;
}

runMe();
alert(addMe);
alert(myVar);

在静态范围语言(如 JS)中,警报 10 和 0。runMe 中的 var myVar(局部变量)会影响该函数中的全局 myVar。但是在 callMe 中没有任何作用,所以 callMe 使用的是全局的 myVar,它仍然为 0。

在动态范围语言(不像 JS)中,callMe 将从 runMe 继承范围,因此 addMe 将变为 20。请注意,在警报时 myVar 仍为 0,因为警报不继承任一函数的作用域。

【讨论】:

  • 例外是 'this' 关键字,其行为类似于动态范围的变量
  • @Jaksa 1. 通过传递“this”,可以修复函数/方法的执行上下文。这展示了动态范围语言的行为,但不一样。 2. 闭包也不会与动态作用域混淆。
【解决方案2】:

如果您的下一行是 callMe();,那么 addMe 将为 10,myVar 将为 0。

如果您的下一行是 runMe();,那么 addMe 将为 20,myVar 将为 10。

请原谅我的提问 - 这与静态/动态绑定有什么关系? myVar 不只是一个全局变量吗,程序代码(将所有内容都解包到调用堆栈上)不会确定值吗?

【讨论】:

    【解决方案3】:

    变量在 JavaScript 中是静态作用域的(动态作用域确实是一个相当混乱的事情:您可以在 Wikipedia 上了解更多信息)。

    但是,在您的情况下,您使用的是全局变量,因此所有函数都将访问同一个变量。 Matthew Flaschen 的回复显示了如何更改它,以便第二个 myVar 实际上是一个不同的变量。

    This Page 解释了如何在 JavaScript 中声明全局变量和局部变量,以防你不太熟悉它。它与大多数脚本语言的做法不同。 (总而言之:如果在函数内声明,“var”关键字使变量成为局部变量,否则变量是全局变量。)

    【讨论】:

      【解决方案4】:

      除非您使用关键字var 来定义您的变量,否则一切最终都会成为window 对象的属性。因此,您的代码将等同于以下内容:

      window.myVar=0;
      
      function runMe(){
          window.myVar = 10;
          window.callMe();
      }
      
      function callMe(){
         window.addMe = window.myVar+10;
      }
      

      如果您牢记这一点,就应该始终清楚发生了什么。

      【讨论】:

        【解决方案5】:

        我想补充一点,lambda 表达式在定义表达式的位置也是静态作用域的。例如,

        var myVar = 0;
        
        function foo() {
            var myVar = 10;
            return { bar: function() { addMe = myVar + 10; }}
        }
        
        var myObj = foo();
        
        var addMe = 6;
        alert(addMe);
        
        myVar = 42;
        myObj.bar();
        
        alert(addMe);
        

        这将显示 6 和 20。

        【讨论】:

          【解决方案6】:

          据我了解,任何不带 var 关键字的变量都会被处理为 global,它的局部作用域是:

          // This is a local scoped variable.
          var local_var = "something"; 
          
          // This is a global scoped variable.
          global_var = "something_else";
          

          作为一种良好的 JS 实践,建议始终添加 var 关键字。

          【讨论】:

            【解决方案7】:
            myVar=0;
            
            function runMe(){
                myVar = 10;
                callMe();
            }
            
            function callMe(){
               addMe = myVar+10;
            }
            

            就输出而言,在这种情况下,myVar 和 addMe 都将是全局变量,就像在 javascript 中一样,如果您不使用 var 声明变量,那么它会隐式地将其声明为全局变量,因此当您调用 runMe() 时myVar 的值为 10,addMe 的值为 20。

            【讨论】:

              猜你喜欢
              • 2011-02-04
              • 1970-01-01
              • 2016-08-31
              • 1970-01-01
              • 2019-10-20
              • 2011-05-13
              • 1970-01-01
              • 2012-09-11
              • 1970-01-01
              相关资源
              最近更新 更多