2

假设我有以下模块,分成多个文件,都能够扩展 skillet

文件1.js:

(function(){
 var privateVar1 = 0;

 var privateFunction1 = function() {
  //function definiton
 };

 skillet.fry() = function() {
  //fry it
  //matchbox.light();
 };

})(window.skillet = window.skillet || {});

文件2.js:

(function(){
 var privateVar2 = 0;

 var privateFunction2 = function() {
  //some private function 
 };

 skillet.grillIt = function() {
  //grill It
  //matchbox.strike(); <-- Shared with File1.js
 };

})(window.skillet = window.skillet || {});

是否可以有一个共享变量/对象,比如matchbox两个模块可以共享而不绑定到window.matchboxor window.skillet.matchbox?即应仅对 File1.js 和 File2.js可见matchbox并且不得在其他地方访问。我怀疑这是否可能,但有没有办法在 JavaScript 中实现这种行为?如果不是,在这方面使用的最佳做法是什么?

(这更像是在一组相关模块之间拥有一个共享的事件总线,而不是全局公开该总线)

4

2 回答 2

3

没有。

“私有”变量在 JS 中起作用只是因为函数声明的范围。没有办法与在完全不同的范围中声明的函数共享该范围。作用域是函数的一个不可更改的属性,一旦它们被创建。

这就是为什么这类事情通常使用_foo样式属性来完成。

skillet._matchbox = { strike: function() { ... } };

下划线前缀是“内部”的约定,并用作提示不要弄乱它。


不过,您也可以通过传递方式获得创意matchbox,尽管在所有情况下,这都意味着提供一种方法来matchbox摆脱它的原始范围。就像也许,制作一个skillet.extend将火柴盒传递给它的参数的方法?

(function() {
  var matchbox = { strike: function() { ... } }
  window.skillet = {
    extend: function(fn) {
      fn(matchbox);
    }
  };
})();

skillet.extend(function(matchbox) {
  var privateVar2 = 0;
  var privateFunction2 = function() {};

  skillet.grillIt = function() {
    //grill It
    matchbox.strike();
  };
}

这允许您以matchbox受控方式在其原始范围之外使用。但它也允许任何人得到matchbox可能不应该得到的东西。

var stolenMatchbox;
skillet.extend(function(matchbox) {
  stolenMatchbox = matchbox;
});
while (stolenMatchbox.count > 0) { stolenMatchbox.strike(); }
alert("Now you are outta matches, sucker!");
于 2012-07-19T19:48:07.640 回答
2

由于您已经将代码分成多个文件,因此您可能会考虑使用像require.js这样的模块加载器。您可以为火柴盒定义第三个模块,然后将其作为参数传递给上面示例中的两个煎锅。使用这种方法,您不必通过窗口全局公开火柴盒。

File1.js 和 require.js 看起来像这样:

define(['matchbox'], function(matchbox){
(function(){
    var privateVar1 = 0;

    var privateFunction1 = function() {
     //function definiton
    };

    skillet.fry() = function() {
       //fry it
       matchbox.light();
    };

 })(window.skillet = window.skillet || {});
});

matchbox.js 看起来像这样:

define([], function() {
  function light() {
     //light implementation
  }

  function strike() {
     //strike implementation
  }

  return {
     light: light,
     strike: strike
  }
}
于 2012-07-19T19:56:26.423 回答