编写代码来处理对象的大多数时候,我们对于对象是什么以及对象可以做什么已经非常了解。然而在有些时候,我们需要以摸索的方式编码,在事先不了解的情况下检查对象。为领域模型对象生成用户界面就是这种情况。理想情况下,我们希望开发一个可重用的解决方案,可以同样地用于任何领域——金融、电子商务、科学可视化等等。本节就介绍这样一个可以在应用中使用的JavaScript库——ObjectViewer。为了让你体验一下活动中的ObjectViewer,图4-7中使用ObjectViewer显示了一个复杂对象图中的几级。

图4-7 这里ObjectViewer用来显示行星系统的等级,每个等级包含一些信息的属性,以及一个保存在数组中的事实列表
所显示的对象代表水星。它是非常复杂的,包含一个图片的URL,一个事实数组,还有一些简单字符串和数字。ObjectViewer可以智能地处理所有这些情况,无需事先知道关于对象类型的任何特定事情。
检查对象、检测其属性和能力的过程称作反射(reflection)。熟悉Java或.NET的读者应该熟悉这个术语,附录B将更加详细地讨论JavaScript的反射能力。这里简短地总结一下,JavaScript对象可以被遍历,好像它是一个关联数组。为了打印出对象的所有属性,我们可以简单地编写这段代码如下:
var description="";
for (var i in MyObj){
var property=MyObj[i];
description+=i+" = "+property+"\n";
}
alert(description);
以一个警告来表现数据是相当原始的,不能与UI的其他部分很好地集成在一起。代码清单4-11代表ObjectViewer对象的核心代码。
代码清单4-11 ObjectViewer对象
objviewer.ObjectViewer=function(obj,div,isInline,addNew){
styling.removeAllChildren(div);
this.object=obj;
this.mainDiv=div;
this.mainDiv.viewer=this;


![]()
库包含两个对象:ObjectViewer,它对对象的成员进行遍历并装配HTML表格来显示数据;PropertyViewer,它作为表格的行呈现单个属性的名称和值。
这样虽然完成了基本的工作,但是遇到了几个问题。首先,它将遍历每一个属性。如果给对象的prototype添加帮助函数,我们可以看到它们。如果对DOM节点添加帮助函数,将看到所有的内建属性,并了解到DOM元素实际上是多么的重要。通常情况下,为选择将对象的哪些属性显示给用户,我们可以在将对象传递给对象呈现器之前,通过在对象上附加一个特殊的属性,即数组,来指定希望显示的对象属性。代码清单4-12演示了如何做这件事。
代码清单4-12 使用objViewSpec属性


![]()
我们定义了属性objViewSpec,ObjectViewer构造函数将会查看每个对象。如果它不能找到这样的属性,就通过在autoSpec()函数中遍历这个对象来创建一个。objViewSpec属性是一个数字数组,每一个元素是一个属性的查找表。就目前而言,我们只关注生成name属性。这个属性的spec传进PropertyViewer的构造函数,可以从spec中获得如何呈现自己的提示。
如果提供一个规范属性给要在ObjectViewer中检查的对象,我们就可以只显示那些我们认为相关的属性。
ObjectViewer的第二个问题是,它不能很好地处理复杂的属性。如果对象、数组和函数附加到string,则调用toString()方法。当属性是对象时,通常返回一些不具有描述性的东西,例如[Object object]。当属性是Function对象时,返回函数的整个源代码。我们可以使用instanceof操作符来区分不同类型的属性。介绍这些之后,让我们看看如何来改善这个查看器。







