使用原型的库子模块的私有名称空间

时间:2014-12-02 01:49:57

标签: javascript

我正在开发一个大型的JavaScript UI模块,想一想iScroll的维度。为了保持理智,我将库分成几个逻辑子模块(如:触摸交互,DOM交互等),使用简单的pubsub系统相互通信。

这些子模块中的每一个都有自己用于存储变量的命名空间。为了使多个库同时运行,构造函数包含一些逻辑,用于将已分配给'toCopy'对象的每个命名空间直接复制到每个新实例中。

基本结构如下所示:

// constructor

function Constructor() {
  for (var key in this.toCopy) {
    // create a deep copy and store it inside the instance
    this[key] = utils.copyObj(this.toCopy[key]);
  }
}

Constructor.prototype.toCopy = {}


// sub-module #1

Constructor.prototype.toCopy._module1Namespace = {}

Constructor.prototype._privateFn = function() { /** do stuff within this._module1Namespace or send events */ }
Constructor.prototype._privateFn = function() { /** do stuff within this._module1Namespace or send events */ }


// sub-module #2

Constructor.prototype.toCopy._module2Namespace = {}

Constructor.prototype._privateFn = function() { /** do stuff with this._module2Namespace or send events */ }
Constructor.prototype._privateFn = function() { /** do stuff with this._module2Namespace or send events */ }

我的问题:我真的不喜欢将每个子模块的命名空间暴露给库的其余部分。虽然我足够自律,不能在子模块#2的功能中访问子模块#1的命名空间,但我希望它在技术上是不可能的。

但是,由于UI库的几个实例必须同时运行,我不能将每个子模块放在一个闭包中,并在此闭包内定义一个私有命名空间。这将导致库的每个实例访问相同的子模块闭包,因此访问相同的命名空间。

此外,将所有内容放在构造函数中而不是放入原型中会为每个新实例创建一组新函数,这与一个好的库的想法相矛盾。

到目前为止,我的研究还没有提出任何有用的模式,我很感谢所有的建议。

1 个答案:

答案 0 :(得分:1)

您似乎希望实例具有在某个对象中定义的标准属性集,而不是在构造函数中显式指定。 “标准”模式将是:

function Foo(a, b) {
  this.a = a;
  this.b = b;
}

Foo.prototype.fn = function() {
  // do stuff
}

但是,您似乎想要创建一个具有标准属性和默认值的对象。也许这应该是构造函数的属性:

Foo.standardProps = {
  a: 'a',
  b: 'b'
}

现在你可以在构造函数中执行:

function Foo() {
  cloneObj(Foo.standardProps, this);
}

其中 cloneObj 复制到您的规范。

请注意,有很多关于如何复制或克隆javascript对象的问题和答案。在一般情况下,由于对副本与克隆的对比,不同类型的对象以及如何处理非对象(如数组,日期和函数)以及主机对象(如DOM元素)存在不同意见,因此很难做到这一点。甚至是Window对象。

最好为您希望制作“深层”副本的Object类型定义一个有限的案例。您甚至可能希望使用getter和setter来明确处理每个案例。