将限定符/标签添加到命名空间

时间:2012-12-15 15:39:36

标签: javascript design-patterns prototype

我正在开发一个Javascript API。其中一个部分是JSON解码器,它接受一个JSON字符串,然后构建适当的对象供程序员使用。其中一些对象是API中的标准对象,但大多数对象都是这些标准对象的应用程序 ad hoc 子对象。

这些应用程序 ad hoc 对象将在Javascript开发之前自动生成,并且它们将存在于命名空间中(应用程序之间的名称不同)。

假设其中一个JSON字符串可能是{"Foo":{"bar":"Hello world!"}},并且应该生成一个对象Foo,其中属性bar具有Hello, world!作为值。这个JSON解码器将检查Foo是否是标准原型之一,如果不是,那么它应该检查所有应用程序 ad hoc 命名空间(我们可以假设它只是一,但这个问题也适用于多个名称空间。)

所以第一个问题:找到那些名称空间。让我们找一些选择:

  • 其中一个选项可能是在JSON解码器中创建一个方法,该方法存储名称空间以便稍后检查它们(每次创建其中一个名称空间时都应该调用此方法)。然而,这引入了一些耦合,因为定义这些命名空间的脚本需要JSON解码器已经可用。我不想要这个。

  • 另一个选项可能是一个全局变量,命名空间在构造时注册自己,解码器在那里浏览。此选项与第一个选项非常相似,但它会污染全局命名空间。我不想要这个。

  • 第三个选项可能是以某种方式标记这些命名空间,因此JSON解码器可以(在加载时)浏览window并在本地存储具有该标签的所有命名空间。这意味着向这些名称空间添加属性,例如IsAFoo,但它必须具有一个值,在这种情况下,根本不会使用它。然后我们只需循环遍历窗口键并检查window[entry].hasOwnProperty("IsAFoo");是否存储它们。由于无趣的价值,我不会想要这个。

  • 我的最后一个选择是使这些命名空间成为“超级命名空间”的实例。我们可以想象我们有一个充当命名空间的对象。我们甚至可以让它们继承这个超级命名空间,但这不是必需的。所以让我们再扩展一下第四个选项,因为它是我选择的选项。

想象一下,我们有了这个对象,它是标准API的一部分,将被称为“超级命名空间”:

var MyCustomQualifier = function (objects) {
    // copy all of the entries to the namespace
    for(var entry in objects) {
        if(objects.hasOwnProperty(entry)) {
            this[entry] = objects[entry];
        }
    }
};

让我们说我们有这样的标准API对象之一:

var SuperFoo = function () {

};

现在,以下代码将是自动生成的代码,包括命名空间的名称:

var MyGlobalNamespace = MyGlobalNamespace || (function () {
    var Foo = function (bar) {
        this.bar = bar;
    };
    Foo.prototype = new SuperFoo();
    Foo.prototype.constructor = Foo;

    Foo.prototype.say = function () {
        return this.bar;
    };

    return new MyCustomQualifier({
        Foo : Foo
    });
})();

通过这种方式,我们使用标准API对象为我们的应用程序提供了MyGlobalNamespace所有对象,并为其提供了自定义业务逻辑。

我们可以执行以下代码,例如,检查一切是否按预期工作:

// this variable would be what the decoder would build,
// but we create it manually here
var foo = new MyGlobalNamespace.Foo("Hello, world!");

console.log("Foo says:", foo.say());
console.log("foo is instance of Foo?", foo instanceof MyGlobalNamespace.Foo);
console.log("foo is instance of SuperFoo?", foo instanceof SuperFoo);

for(var entry in window) {
    if(window[entry] instanceof MyCustomQualifier) {
        console.log(entry + " is a MyCustomQualifier!");
    }
}

将输出:

Foo says: Hello, world!
foo is instance of Foo? true
foo is instance of SuperFoo? true
MyGlobalNamespace is a MyCustomQualifier!

那么您如何看待这些选项以及我对第四种选择的回答?你有什么额外的方法吗?重要的是代码是纯Javascript而没有框架。

谢谢!

0 个答案:

没有答案