【问题标题】:Javascript Public/Private VariablesJavascript 公共/私有变量
【发布时间】:2011-12-03 10:28:12
【问题描述】:

我有一个包含公共和私有变量的对象。公共变量被分配给私有变量(我认为),但是,每当我用函数修改私有变量时,公共变量都不会更新。

var foo = (function() {
    //Private vars
    var a = 1;

    return {
        //Public vars/methods
        a: a,
        changeVar: function () {
            a = 2;
        }
    }
})();
alert(foo.a);  //result: 1
foo.changeVar();
alert(foo.a);  //result: 1, I want it to be 2 though

现在我知道,如果我将 changeVar 中的行更改为 this.a = 2; 它可以工作,但它不会更新私有变量。我想同时更新私有变量和公共变量。这可能吗?

JsFiddle showing problem

【问题讨论】:

标签: javascript variables scope private public


【解决方案1】:

当您在要返回的对象中设置 a 键时,即会生成“私有”a 变量的副本

您可以使用 getter 函数:

return {
    //Public vars/methods
    a: function() { return a; },
    changeVar: function () {
        a = 2;
    }
};

或者您可以使用 Javascript 的内置访问器功能:

obj = {
    //Public vars/methods
    changeVar: function () {
        a = 2;
    }
};
Object.defineProperty(obj, "a", { get: function() { return a; } });
return obj;

【讨论】:

【解决方案2】:

是的,如果您使用的是较新的浏览器:

var foo = (function() {
    var a = 1;
    return {
        get a() { return a; },
        changeVar: function () {
            a = 2;
        }
    }
})();

See a demo on JSFiddle.

还有一种更兼容的方法,但需要更改使用它的代码:

var foo = (function() {
    var a = 1;
    return {
        getA: function() { return a; },
        changeVar: function () {
            a = 2;
        }
    }
})();
alert(foo.getA()); // rather than foo.a

如果这两种方法都不适合你,你必须要么总是分配两者,要么总是引用一个(如果你打算公开的话,它必须是公共的。

【讨论】:

    【解决方案3】:

    我通常使用这种模式,但我没有看到很多人这样做。 我这样做是为了避免必须以任何特殊方式订购我的方法。如果都是public,那么通常必须确保调用的方法在方法调用之前声明

    var person = new Person("Mohamed", "Seifeddine");
    person.getFullname();
    person.getFirstname();
    person.getLastname();           
    
    function Person(firstname, lastname) {
        var firstname, lastname;
    
        (function constructor(){
            setFirstname(firstname);
            setLastname(lastname)
        })();
    
        this.getFullname = getFullname;   // Makes getFullName() public 
        function getFullname() {
            // Will allow you to order method in whatever order you want. 
            // If we where to have it as just this.getFullname = function () {...} and same for firstname 
            // as it is normally done, then this.getFirstname would have to be placed before this method. 
            // A common pain in the ass, that you cannot order methods as you want!    
            return getFirstname() + ", " + getLastname();   
        }               
    
        this.getFirstname = getFirstname;
        function getFirstname() {
            return firstname;
        }
    
        function setFirstname(name){
            firstname = name;
        }
    
        this.getLastname = getLastname;
        function getLastname() {
            return lastname;
        }
        function setLastname(name) {
            lastname = name;
        }    
    }
    

    【讨论】:

      【解决方案4】:

      其他人已经给了你答案,但你的问题似乎更多的是关于设置值。

      var foo = (function() {
          //Private vars
          var a = 1;
      

      这是对 a 的一个赋值,它是匿名函数的本地函数。

          return {
              //Public vars/methods
              a: a,
      

      这也是将 a 的值分配给将由 foo 引用的对象的 a 属性的一种赋值。 .对变量a的后续更改不会影响该属性的值。

              changeVar: function () {
                  a = 2;
      

      这里,a 将解析为对“外部”a 的引用,因此它会更改变量的值,但不会更改foo.a。如果你知道它总是作为 foo 的方法被调用,你可以改为:

              changeVar: function () {
                  this.a = 2;
      

      因此它将 a 解析为 foo 的属性,而不是作用域链(因此变量 a)。

              }
          }
      })();
      

      【讨论】:

      • 我在 OP 中声明 this.a 引用公共 'a' 而不是私有 'a' 但我想同时更改两者,这是不正确的吗?我修改了已接受答案的第一个解决方案,使其也成为二传手。 a: function(value) {if(arguments.length > 0) a = value; else return a;
      • 是的,您可以同时更改两者。访问一个作为对象属性,另一个作为范围链上的变量,例如changeValue: function(value){this.a = value; a = value;}.
      • 这就是你问的,不是吗?你不能用一个表达式来改变两者,它需要两个表达式。
      • 通过 getter/setter 将它们合并在一起似乎更好。
      猜你喜欢
      • 2011-05-25
      • 2012-05-29
      • 2012-09-03
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      相关资源
      最近更新 更多