【问题标题】:Javascript revealing module pattern and variablesJavascript揭示模块模式和变量
【发布时间】:2014-02-05 22:51:26
【问题描述】:

我的问题和这个Javascript revealing module pattern, public properties一模一样

在那个帖子中,给出了答案,但没有给出“为什么”。这是用我自己的示例重申的相同问题:

myApp.User = function () {
    var firstName = 'Default',
        lastName = 'Default';

    function setFirstName(name) {
        firstName = name;
    }

    function setLastName(name) {
        lastName = name;
    }

    function getFirstName() {
        return firstName;
    }

    function getLastName() {
        return lastName;
    }

    return {
        getLastName: getLastName,
        **getFirstName: getFirstName**,
        setLastName: setLastName,
        setFirstName: firstName
    };
};

在这种情况下,User().getFirstName 总是评估为“默认”——即使我通过 setFirstName 函数将其更改为其他值。

如果我用 setFirstName 替换:

 return {
    getLastName: getLastName,
    **getFirstName: getFirstName**,
    setLastName: setLastName,
    setFirstName: firstName
};

我能够访问更改后的值。我知道 var firstName 是按值传递的,这就是不反映更新值的原因。我不明白该功能有什么特别之处。指向函数中值的指针在哪里?为什么所有功能都“神奇”地访问更新?

【问题讨论】:

  • 如果它“总是评估为'默认'”,那么您不会首先在同一个对象上调用setFirstName。此外,{ setFirstName: firstName } 暗示 obj.setFirstName 不是 一个函数(因为firstName 不是 一个函数),所以你不能调用它,甚至如果你愿意。 (而且由于代码没有改变 firstName 变量.. 当然它总是'默认'。)
  • 返回对象的最后一个属性不应该是setFirstName: setFirstName而不是setFirstName: firstname吗?
  • @user1066946 同意。我刚刚完成了该链接的阅读,您是对的-这是对闭包问题的一种变体。阅读后,我现在明白它为什么起作用了

标签: javascript


【解决方案1】:

指向函数中值的指针在哪里?

在函数的作用域中——它包含了它可以访问的所有变量。这种访问实际上使函数成为closure。

为什么所有功能都“神奇地”访问更新?

因为所有函数共享在更高范围内声明的变量。

【讨论】:

  • 将此标记为正确,因为它是我问题的核心。基本上我不理解闭包,所以这种行为看起来很奇怪。
【解决方案2】:

他们不会“神奇地”访问更新。它们在在myApp.User 内,这就是它们可以访问变量位置的原因。

当您执行myApp.User().getFirstName() 时,因为getFirstName 在函数内部(作用域),它将能够访问在函数内部和函数外部声明的变量。

function a(){
    var b = "hello";
    return {
        setB: function(c){ b = c; },
        getB: function(){ return b; }
    };
}

var obj = new a();
obj.getB();         //hello
obj.setB("new");
obj.getB();         //new

在上面的示例中,getB 和 setB 都存在于您的对象中,它们可以访问 a() 范围内的所有变量。

【讨论】:

    【解决方案3】:

    看看你在第一个例子中做了什么

    setFirstName: firstName
    

    setFirstName 不是对函数“setFirstName”的引用,而是对变量“firstName”的引用……您无权访问函数“setFirstName”。您仍然无法使用该功能,因此您无法随意修改 firstName。

    它超出了范围 - 您没有归还它,因此可以说它可供外界使用。它在功能范围“之外”不可用。返回函数(),并应用“setFirstName”,如下所示。

    试试这个;

    myApp.User = function () {
        var firstName = 'Default',
            lastName = 'Default';
    
        function setFirstName(name) {
            firstName = name;
        }
    
        function setLastName(name) {
            lastName = name;
        }
    
        function getFirstName() {
            return firstName;
        }
    
        function getLastName() {
            return lastName;
        }
    
        return {
            getLastName: getLastName,
            getFirstName: getFirstName,
            setLastName: setLastName,
            setFirstName: setFirstName
        };
    }();
    myApp.User.setFirstName('bill');
    myApp.User.getFirstName();
    

    【讨论】:

      【解决方案4】:
      var User = function () {
          var firstName = 'Default',
              lastName  = 'Default';
      
          return {
              getLastName:  function() { return lastName; },
              getFirstName: function() { return firstName; },
              setLastName:  function(name) { lastName = name; },
              setFirstName: function(name) { firstName = name; },
              getName:      function() { return firstName + ' ' + lastName; }
          };
      };
      
      var u = User(),
          v = User();
      console.log( u.getName() + ' - ' + v.getName() );
      // Outputs: 'Default Default - Default Default'
      u.setFirstName( 'Alice' );
      u.setLastName( 'Bob' );
      console.log( u.getName() + ' - ' + v.getName() );
      // Outputs: 'Alice Bob - Default Default'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-12
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 1970-01-01
        • 2012-02-12
        • 1970-01-01
        相关资源
        最近更新 更多