【问题标题】:Javascript variable scope and valueJavascript变量范围和值
【发布时间】:2015-07-28 03:15:06
【问题描述】:
var namepace = (function () {

    var loca = 5;

    var getLocal = function () {
        loca += 1;
        return loca;
    };

    return {
        glob: getLocal,
        blog: loca,
        frog: function () {
            return loca;
        }
    };
})();

alert(namepace.glob());
alert(namepace.blog);
alert(namepace.frog());

我的问题是为什么函数 alert(namepace.blog); 返回 5 而不是 6 如我所料?

【问题讨论】:

    标签: javascript function namespaces scope


    【解决方案1】:

    在运行 JavaScript 程序时考虑执行上下文会有所帮助。 JavaScript 计算引用(而不是直接计算值)。

    全局上下文由全局变量和对象组成。在这种情况下是(在 JavaScript 解释器读取命名空间指令时):

    namespace = {f}  // namespace references a function
    

    这意味着命名空间正在引用一个函数。在第一个警报中,为命名空间创建了以下执行上下文:

    loca = 5                // loca references the value 5
    getLocal = {f}          // getLocal references a function
    return {                // return object with glob, blog and frog as properties
      glob = { getLocal() } // references the function getLocal()
      blog = 5              // blog references same value as loca: 5
      frog = {f}            // references anonymous function
    }
    

    因此调用了函数 glob。 glob 引用了一个名为 getLocal 的函数。 glob的执行上下文如下:

    loca = 6      // loca now references the value 6
    return loca   // return value referenced by loca
    

    下一个调用是 blog,这个调用返回值 5。它不引用 loca。它仅引用 loca 在创建执行上下文时所具有的值。在创建执行上下文时,loca 引用了 5,因此 blog 引用了 5。 无论你多久调用一次 glob,blog 仍然会引用 5 的值。

    在最后一个警告语句中调用了青蛙。 frog 引用了一个现在正在执行的匿名函数。 frog的执行上下文如下

    return loca // Go and get the value that is referenced by loca
    

    基本上就是这样。每当您认为价值时,请尝试考虑“对价值的引用”。这有助于习惯它。并尝试在程序运行时可视化执行上下文(例如作为人工调试器)。

    【讨论】:

      【解决方案2】:

      这里要理解的重要一点是,JavaScript 中的所有名称都是对其他对象的引用。

      当您使用 Object 字面量创建 Object 时,左侧名称用于引用已由右侧名称引用的对象。

      在这种情况下,当你这样做时

          blog: loca,
      

      你说blog是指loca所引用的值,即5。稍后当你增加loca时,它变成6,这意味着它引用了一些其他值,但是@987654328 @ 仍然指的是值5

      这就是你收到5的原因。

      但是当你这样做时

      namepace.frog()
      

      您正在获取loca 引用的当前值。由于它在getLocal 中分配了6,因此您将获得6

      增量创建新的数字对象

      为了更清楚,当你这样做时

      loca += 1;
      

      loca++;
      

      内部发生的事情是这样的

      oldValue = loca
      newValue = oldValue + 1
      loca = newValue
      

      来自 ECMAScript 5.1 规范的参考,用于 +=++

      由于数字是不可变对象(你能改变5的值吗?你不能,这就是为什么它被称为不可变对象),一个新的数字对象被添加到它上面并命名为loca用于引用新对象。


      可变对象

      如果你考虑可变对象,

      var namepace = (function () {
      
          var loca = [];
      
          return {
              glob: function () {
                  loca.push(1);
                  return loca;
              },
              blog: loca,
              frog: function () {
                  return loca;
              }
          };
      })();
      
      console.log(namepace.glob());
      // [ 1 ]
      console.log(namepace.blog);
      // [ 1 ]
      console.log(namepace.frog());
      // [ 1 ]
      

      现在,blogloca 都引用同一个数组对象。 glob 中发生的事情称为mutating。您只是将一个元素添加到使用两个名称 blogloca 引用的数组对象中。这就是为什么namepace.blog 也会打印[ 1 ]

      【讨论】:

        【解决方案3】:

        当分配给namespace.blog 时,您使用的是按值传递给设置器。这意味着没有对 loca 的引用。

        当您通过 namespace.frog 访问值时,您使用的是原始变量,该变量利用 JavaScript 的闭包作用域解析为 loca,这是本地作用域链上的下一个可用定义。

        您可以在此处阅读范围界定:What is the scope of variables in JavaScript?

        【讨论】:

          【解决方案4】:

          这是一个逻辑问题。当功能需要一些时间时。在那个时间变量分配..看下面的代码。试试这个

          var namepace = (function () {
          
              var loca = 5;
          
              var getLocal = function () {
                  loca += 1;
                  return loca;
              };
              console.log(loca);
          
              return {
                  glob: getLocal,
                  blog: loca,
                  frog: function () {
                      return loca;
                  }
              };
          })();
          
          alert(namepace.glob());
          alert(namepace.blog);
          alert(namepace.frog());
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-21
            • 2020-02-07
            • 2012-12-23
            • 2011-05-10
            • 2011-07-07
            相关资源
            最近更新 更多