Generic object creation, object inspection
JavaScript 1.1
makeObj()
, parseObj()
,
objProfile()
Now JavaScript objects. So many things to do with them, so little time to try them all. objects.js provides two utilities. One is a generic object constructor, the other is a basic object inspector. Open ch06objects.html in your browser. Figure 6.15 shows you what you get.
Object inspector functions parseObj()
and
objProfile()
reveal the properties of two objects:
one represented by variable someObject
; the
other is the location object of the window. Have a look at
objects.html
in Example 6.10 to
see how this gets under way.
Example 6-10. objects.html
1 <HTML> 2 <HEAD> 3 <TITLE>objects.js Example</TITLE> 4 <STYLE type="text/css"> 5 <!-- 6 td { font-family: courier new; font-size: 14} 7 --> 8 </STYLE> 9 <SCRIPT LANGUAGE="JavaScript1.1" SRC="objects.js"></SCRIPT> 10 </HEAD> 11 <BODY> 12 <SCRIPT LANGUAGE="JavaScript1.1"> 13 <!-- 14 15 function plainOldObject() { 16 this.name = 'some name'; 17 this.numba = 1000; 18 this.objInherit = new makeObj('propertyOne', 'thisProperty', 19 'propertyTwo', 'thatProperty', 'propertyThree', 'theOtherProperty'), 20 return this; 21 } 22 23 var someObject = new plainOldObject(); 24 25 document.write(objProfile('someObject', 'self.location')); 26 //--> 27 </SCRIPT> 28 29 </BODY> 30 </HTML>
Notice line 23 sets variable someObject equal to
a new plainOldObject()
. The
plainOldObject()
constructor has several
properties, including name, numba, and
objInherit. objInherit
represents an object made from the generic object
constructor makeObj()
found in
objects.js. Take a look at the source file in
Example 6.11.
Example 6-11. objects.js
1 function makeObj() { 2 if (arguments.length % 2 != 0) { 3 arguments[arguments.length] = ""; 4 } 5 for ( var i = 0; i < arguments.length; i += 2 ) { 6 this[arguments[i]] = arguments[i + 1] ; 7 } 8 return this; 9 } 10 11 function parseObj(obj) { 12 var objStr = ''; 13 for (prop in obj) { 14 objStr += '<TR><TD>Property: </TD><TD><B>' + prop + 15 '</B></TD><TD>Type: </TD><TD><B>' + typeof(obj[prop]) + 16 '</B></TD><TD>Value: </TD><TD><B>' + obj[prop] + 17 '</B></TD></TR>'; 18 if (typeof(obj[prop]) == "object") { 19 objStr += parseObj(obj[prop]); 20 } 21 } 22 return objStr; 23 } 24 25 function objProfile() { 26 var objTable = '<TABLE BORDER=2 CELLSPACING=0><TR><TD><H1>' + 27 'Object Profile</H1></TD></TR>'; 28 for (var i = 0; i < arguments.length; i++) { 29 objTable += '<TR><TD><BR><BR><H2><TT>' + (i + 1) + ') ' + 30 arguments[i] + '</H2></TD></TR>'; 31 objTable += '<TR><TD><TT><TABLE CELLPADDING=5>' + 32 parseObj(eval(arguments[i])) + '</TABLE></TD></TR>'; 33 } 34 objTable += '</TABLE><BR><BR><BR>'; 35 return objTable; 36 }
Let’s first have a look at makeObj()
; here
are lines of the source file:
function makeObj() { if (arguments.length % 2 != 0) { arguments[arguments.length] = ""; } for ( var i = 0; i < arguments.length; i += 2 ) { this[arguments[i]] = arguments[i + 1] ; } return this; }
This constructor builds properties by assigning pairs of arguments
passed in. If there is an odd number of arguments passed (meaning one
argument won’t make a pair), makeObj()
assigns an additional element of empty string value to the
arguments array. Now every argument element has
a buddy. makeObj()
then iterates through the
arguments elements by twos, assigning the first element of the pair
as an object property name, and the second element of the pair as the
value of the previously named property. That is, calling
makeObj('name',
'Madonna', 'occupation',
'singer/songwriter')
would return a reference to an object with the following
properties:
this.name = 'Madonna'; this.occupation = 'singer/songwriter';
Therefore, variable objInherit now refers to an object and has the following properties:
objInherit.propertyOne = 'thisProperty'; objInherit.propertyTwo = 'thatProperty'; objInherit.propertyThree = 'theOtherProperty';
Note that all the properties have strings as values. You can
certainly pass in numbers, objects, and the like. Function
makeObj()
is great for creating multiple objects,
each with different properties, without having
to define a constructor for each.
The other object inspected is the location object. Pretty
straightforward, but how does the inspection work? Functions
objProfile()
and parseObj()
work together recursively to “drill down” into object
properties and create a table of results. Each table row identifies
the object property name, the property object type, and the value to
which it is associated. Let’s begin with
objProfile()
:
function objProfile() { var objTable = '<TABLE BORDER=2 CELLSPACING=0><TR><TD><H1>' + 'Object Profile</H1></TD></TR>'; for (var i = 0; i < arguments.length; i++) { objTable += '<TR><TD><BR><BR><H2><TT>' + (i + 1) + ') ' + arguments[i] + '</H2></TD></TR>'; objTable += '<TR><TD><TT><TABLE CELLPADDING=5>' + parseObj(eval(arguments[i])) + '</TABLE></TD></TR>'; } objTable += '</TABLE><BR><BR><BR>'; return objTable; }
objProfile()
is the function you call and pass
parameters. See line 25 in objects.html
:
document.write(objProfile('someObject', 'self.location'));
The arguments passed in aren’t objects at all. They’re
strings. They’ll reflect objects soon. Passing in the string
equivalent allows JavaScript to display these objects by name to the
page. Once the necessary table TR
s and
TD
s are created, these string arguments passed in
to objProfile()
are iteratively de-referenced with
the eval()
method in line 32 and passed to
parseObj()
. Watch what happens then:
function parseObj(obj) { var objStr = ''; for (prop in obj) { objStr += '<TR><TD>Property: </TD><TD><B>' + prop + '</B></TD><TD>Type: </TD><TD><B>' + typeof(obj[prop]) + '</B></TD><TD>Value: </TD><TD><B>' + obj[prop] + '</B></TD></TR>'; if (typeof(obj[prop]) == "object") { objStr += parseObj(obj[prop]); } } return objStr; }
Each dereferenced string arrives as an object and is called
obj. Using the for ... if loop,
parseObj()
iterates through all properties in
obj, accumulating a string of its property,
type, and value along with appropriate table tags.
parseObj()
accesses the object type with the
typeof()
operator. Once the property, type and
value have been added to the string, parseObj()
checks to see whether the type of that particular property is an
object. If so, parseObj()
calls itself and passes
in the property (which is an obj object). This
recursion allows the “drill down” effect to get to the
bottom of, and reveal, a top-level object’s internal hierarchy.
When parseObj()
has no more objects to parse, the
entire string of properties, types, values, and table tags, reflected
in variable objStr,
is eventually returned to
function objProfile()
.
objProfile()
then concatenates this string to the
other table rows and cells that it created. This string, reflected in
variable objTable,
is finally written to the page
in line 25 of objects.html.
These object inspection functions are designed for relatively small objects, such as user-created objects. Both Navigator and IE will choke on the script if there is too much recursion. For example, try changing line 25 of objects.html from this:
document.write(objProfile('someObject', 'self.location'));
to this:
document.write(objProfile('document'));
Now load the document into MSIE. You’ll no doubt receive a stack overflow message. Try this in line 25 with Navigator:
document.write(objProfile('window'));
You get this in the JavaScript console: JavaScript Error: too much recursion
52.15.63.145