我正在开发一个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而没有框架。
谢谢!