1

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

这些应用程序特别对象将在 Javascript 开发之前自动生成,并且它们将存在于命名空间中(其名称因应用程序而异)。

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

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

  • 其中一个选项可能是在 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
    });
})();

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

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

// 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 且没有框架,这一点很重要。

谢谢!

4

0 回答 0