2012-07-19 61 views
2

说我有以下模块,跨多个文件分割既能够延伸skillet是否有可能让变量只显示“模块”及其扩展名?

File1.js:

(function(){ 
var privateVar1 = 0; 

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

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

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

File2.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.matchboxwindow.skillet.matchbox?即知名度matchbox应该只适用于File1.js和File2.js,并且不能在其他地方访问。我怀疑是否有可能,但有没有办法在JavaScript中实现这样的行为?如果不是,这方面的最佳做法是什么?

(它更像具有共享事件总线一组相关模块中,而不暴露全局该总线)

回答

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!"); 
2

由于您已将代码划分为多个文件,因此您可以使用模块加载器(如require.js)进行研究。您可以为火柴盒定义第三个模块,然后将它作为参数传递给上面示例中的两个skille。采用这种方法,您不必通过窗口全局公开火柴盒。

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 || {}); 
}); 

火柴盒。js看起来像这样:

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

    function strike() { 
    //strike implementation 
    } 

    return { 
    light: light, 
    strike: strike 
    } 
} 
+0

我还没有使用requirejs之前。你能否详细说明前两行的含义?封装是如何实现的? – PhD 2012-07-19 20:06:29

+1

Require.js是一个JavaScript模块加载器,它遵循[异步模块定义(AMD)范例](http://requirejs.org/docs/whyamd.html)。通俗地说,这是一种在javascript的#include/import/using类型语法中定义模块依赖关系的方法。 我包装了File1.js的define()调用指定它取决于模块的“火柴盒”,一旦它完成非同步加载,它将作为参数“火柴盒”传递给函数。使用这种方法,不需要将您的火柴盒模块注册到全局名称空间。 – GreatTall1 2012-07-20 16:16:21

相关问题