模块模式中的变量范围

时间:2014-11-11 19:00:14

标签: javascript

我试图了解如何在以下脚本中触摸/更改/增加我的私有范围变量x。我在这里使用Module模式,并认为我可以从公共返回模块声明的属性或方法进入并设置私有变量,但我尝试的任何工作都没有。相关:何时声明func的新实例与将func作为静态delcared变量进行访问?



    var func = (function() {
      var x = 1;
      var squareX = function() {
        return x * x;
      };
      var addOne = function() {
        x++;
      }
      return {
        X: x,
        Xq: squareX,
        AddOne: addOne
      };
    });

    func().X = 9; // expecting privately scoped x = 9
    func().AddOne(); // expecting privately scoped x = 10
    document.write(func().Xq()); // expecting 100 actual = 1




3 个答案:

答案 0 :(得分:3)

模块模式的要点是创建一个持久性私有范围,它从外部是不可见的。不幸的是,每次调用func时,您都会创建一个 new 范围(带有新的返回函数及其闭包),因此您的所有操作都会被丢弃。

不要多次调用func,只需执行一次即可设置“模块”(您甚至可以使用IIFE立即执行此操作),然后对结果执行操作。 / p>

var func = function() {
  var x = 1; // this is the private variable

  var squareX = function() {
    return x * x;
  };
  var addOne = function() {
    x++;
  };

  return {
    // Note, you can't just do "X: x,"
    // since that will just create a copy;
    // you have to use properties
    get X() { return x; },
    set X(val) { x = val; },

    Xq: squareX,
    AddOne: addOne
  };
};

var funcModule = func();
funcModule.X = 9;
funcModule.AddOne();
document.write(funcModule.Xq());

请注意,您需要X模块属性的显式getter和setter的原因是因为您需要能够修改内部(隐藏)变量x。所有现代浏览器都提供属性,包括IE9 +。如果您在IE8或更低版本中工作,则需要定义明确的getXsetX方法,并直接调用它们(您不仅可以执行funcModule.X = 5

答案 1 :(得分:2)

你需要一个二传手,你需要一个IIFE:

var func = (function() {
  var x = 1;
  var squareX = function() {
    return x * x;
  };
  var addOne = function() {
    x++;
  }
  return {
    X: function(value) {
      if (value !== undefined) {
        x = value;
      }
      return x;    // we can use this as a getter too!
    },
    Xq: squareX,
    AddOne: addOne
  };
})(); // <-- this actually runs the function - this makes it an IIFE

document.write("X is " + func.X() + "</br>");

func.X(9); // expecting privately scoped x = 9

document.write("now X is " + func.X() + "</br>");

func.AddOne(); // expecting privately scoped x = 10

document.write("now X is " + func.X() + "</br>");

document.write(func.Xq()); // expecting 100 actual = 100

答案 2 :(得分:0)

您正在使用Revealing Module Pattern来隐藏您的私有实例变量。使用该模式时,必须使用某种setter来更改私有实例变量。这是另一个StackOverflow post,其他人遇到了同样的问题。

我不建议你使用Revealing Module Pattern。事实上,我刚刚给talk NationJS 2014标题为&#34; The Revealing Module is anti-Pattern&#34;。