【发布时间】:2015-04-08 05:19:26
【问题描述】:
我有一个我非常喜欢的模块系统的想法,我正在尝试为我的一个项目创建一个模块系统,问题是我似乎无法弄清楚。这个想法很简单,没有什么复杂的,而且非常简单,但我想我错过了一些东西,因为我花了几个小时来尝试一些东西。
基本上我想要做的就是在一个模块中拥有 4 个变量,公共的、受保护的、包的和私有的,以及 3 个函数增强、扩展和子模块。
这个想法是每个模块都是一个匿名函数,它将一个公共接口保存到一个窗口变量,并且让其他所有东西都无法访问。也就是说,公共变量和 3 个函数中的任何内容都是唯一的公共接口。
理想情况下,通过这种设置,您可以直接使用扩展函数扩展任何模块,将模块扩展为与扩展函数的父/子关系,并使用子模块函数在该模块上创建子模块。根据选择的变量和方法,可以访问变量,例如,所有子模块和扩展都可以访问包,而子模块无法访问受保护的。
这也应该形成一个链,每个子模块或每个扩展都可以访问其父数据并有空间添加自己的数据。我还应该注意,其意图不像每个实例都有自己的所有变量副本的类,而是每个模块中只有一个变量池,并且它们根据所采取的操作相互链接。
我下面的内容是我到目前为止提出的内容,但它并不完全正确,也不太适合,因为它更倾向于像 setup 这样的类,并且真的不像我想要的那样工作,如上所述但是应该让你明白我在说什么。
非常感谢任何帮助,下面的代码和 jsfiddle 链接
https://jsfiddle.net/0ghbxdpo/
function Module()
{
// Accessible to everything
this._public = {};
// Accessible to all extensions and submodules
this._package = {};
// Accessible only to extensions of the same module
this._protected = {};
// Accessible only to augmentations
this._private = {};
}
// Augments this module and returns the newly augmented module, using
// the return value isn't nesasary as the actual module would have successfully
// been augmented
// Access to all properties
Module.prototype.augment = function augment(augmentation)
{
return augmentation({
_public: this._public,
_package: this._package,
_protected: this._protected,
_private: this._private
});
}
// Create a new module with this one as its parent
// Access to all but this modules private variables
Module.prototype.extend = function extend(extension)
{
var obj = new Module();
obj._public._parent = this._public;
obj._package._parent = this._package;
obj._protected._parent = this._protected;
// Execute the extension module under the context of a new module
// with all but the private variables as its parents
return extension.call(obj);
}
// Create a new module and assign it to one of the 4 scope variables, public by default
// Access only to public and package modules
Module.prototype.submodule = function submodule(moduleName, module, scope)
{
var obj = new Module();
obj._public._parent = this._public;
obj._package._parent = this._package;
// Run the submodule code under the context of the new module
var tmp = module.call(obj);
// Then assign it to the correct scope variables
if(scope === "protected")
return this._protected[moduleName] = tmp;
else if(scope === "package")
return this._package[moduleName] = tmp;
else if(scope === "private")
return this._private[moduleName] = tmp;
else
return this._public[moduleName] = tmp;
}
// Some test to play around and test it out
// This isnt ideal as theres no way to actually setup anything with the initial module
// Also it reveals all the scopes to the public
window.CoolTest = new Module();
// This fails with an error as "this" points to the wrong object so the whole
// thing is created wrong and fails. You cant use call, apply, or bind from here as
// the public should not have access to anyting but the public variables
// The other scope variables are supposed to be stored internally and automatically
// used to create the submodule without ever exposing them
window.CoolTest.submodule("sub", function()
{
this._public.hello = "world";
});
【问题讨论】:
标签: scope closures javascript