var aNames= [ "Adam", "Bill", "Carl" ]; // create an array
alert( aNames[0] ); // Adam -- look it up by its index number
// iterate through them
for ( var j=0; j< aNames.length; j++ ) {
alert( aNames[j] ); //
}
But JavaScript also supports Associative Arrays (aka Maps or Dictionaries) -- providing a way to access list items not just by position, but by an associated key.
// this seems reasonable...
var aNames= new Array();
aNames[ "Anderson" ]= "Adam";
aNames[ "Browne" ]= "Bill";
aNames[ "Crawford" ]= "Carl";
alert( aNames[ "Anderson" ] ); // shows Adam (as expected)
// ... but this might not seem reasonable:
alert( aNames.length ); // shows 0 !!! (why not 3?)
The above code creates an Array and then puts nothing into any of the array elements!
var mapNames= new Object(); // or: var mapNames= {};
mapNames[ "Anderson" ]= "Adam";
mapNames[ "Browne" ]= "Bill";
mapNames.Crawford = "Carl"; // alternate syntax
mapNames[ 2 ]= "Two";
alert( mapNames.length ); // undefined (it is not an Array)
for ( var j in mapNames ) { // show the keys
alert( j ); // Anderson, Browne, Crawford, 2
}
for ( var j in mapNames ) { // show the data associated with each key
alert( mapNames[j] ); // Adam, Bill, Carl, Two
}
These key/value pairs are often called properties of the object.
var mapNames= {
"Anderson" : "Adam", // syntax is key:value
"Browne" : "Bill",
"Crawford" : "Carl"
};
for ( var n in mapNames ) { // show the keys and values
alert( n+ "=" + mapNames[n] ); // Anderson=Adam, Browne=Bill, etc...
}
The key is on the left and the value is on the right. The value does not need to be a string or other simple value. It can be an array, or it can be another object that has its own map of key/value pairs (properties). You can make the object as complex as you want. See JSON for some related information and examples.
...
DoThat( {color:"Red", font:"Arial" } ); // unnamed object
...
function DoThat( o ) {
alert( o.color ); // shows: Red
alert( o.font ); // shows: Arial
}
The caller creates an anonymous object (a map of key:value pairs) and the called function can then access the values by name. Note the shortcut used in the call: If the key is a text string, you can omit the quotes when you identify the property.
var o= {}; // or: var o= new Object();
o.lastName= "Anderson";
o.age= 17;
... later that day ...
o.LastName= "Smith"; // oops, uppercase L
If you misspell a key name, then you have just added a new property to the object. That's probably not what you wanted to do! Though JavaScript associative maps don't need to be declared in advance, doing so can help you to avoid some errors. Let's look at a way of "formalizing" the object properties.
function PersonRec() {
this.sNameLast= ''; // the "this." part is required
this.sNameFirst= '';
this.nAge= 0;
this.fIsParent= false;
this.asChildren= new Array();
}
Here we have defined an object with a set of specific properties. When I get to this stage, I start to think of the object as a record with fields.
function PersonRec(p1,p2,p3,p4,p5) {
this.sNameLast= (p1 != undefined) ? p1 : '';
this.sNameFirst=(p2 != undefined) ? p2 : '';
this.nAge= (p3 != undefined) ? p3 : -1;
this.fIsParent= (p4 != undefined) ? p4 : false;
this.asChildren=(p5 != undefined) ? p5 : new Array();
}
That version accepts a variable number of parameters. Missing parameters are detected and the corresponding fields will be assigned default values. To create an instance of the record, use syntax like:
var rPer1= new PersonRec(); // populated with defaults
var rPer2= new PersonRec( "Anderson", "Adam", 35, true, ["Andy","Al"] ); // all data
var rPer3= new PersonRec( "Browne", "Bill" ); // with some data and some defaults
rPer3.nAge= 43; // update the record
rPer3.sNameFirst= "William"; // update the record
The constructor can do a lot more than just assign values. It can calculate fields based on other fields, or pre-populate a lookup table, or read and parse data from a webpage, or grab data from a database -- any kind of initialization that you want to have happen each time an instance of the record object is created.
function PersonRec(p1,p2) {
this.sNameLast= p1;
this.sNameFirst=p2;
...
//-------------------------------- add some methods; i.e., member functions
this.GetFullName= function() {
return( this.sNameFirst +" "+ this.sNameLast );
};
this.toString= function() {
var s= "Name: " + this.GetFullName() + "\n";
s+= "Age: " + this.nAge + "\n";
if ( this.fIsParent ) {
s+= "Children: " + this.asChildren;
}
return( s );
};
}
The Object.toString() member already exists, but it just outputs [Object object], which is not too useful. It's handy to write an override function like that shown, so that you can get a quick display of the data for easy debugging.
var arPersons = [
new PersonRec("Anderson", "Adam", 35, true, ["Andy","Alice"] ),
new PersonRec("Browne", "Bill", 25, false ),
new PersonRec("Crawford", "Carl", 45, true, ["Caroline"] )
];
Now that we have defined an array of these records, we can easily cycle through them using JavaScript array syntax:
var oCombo= document.getElementById('selectName'); // a <SELECT> element
oCombo.options.length=0; // clear out the box
oCombo.options.length=arPersons.length; // prepare to repopulate
for (var j=0; j<arPersons.length; j++) {
oCombo.options[j].text= arPersons[j].sNameLast;
}
... later, see what's been selected ...
var i= oCombo.selectedIndex;
alert( arPersons[i].sNameFirst +" is "+ arPersons[i].nAge );
And to generate a table like this:
function BuildOutputTable() {
var sOut="<table border=2>";
sOut +="<tr>";
sOut +="<td>Last Name</td><td>First Name</td><td>Age</td><td># of Kids</td>"
sOut +="</tr>";
for ( var j=0; j<arPersons.length; j++ ) {
var rP= arPersons[j]; // a PersonRec object
sOut += "<tr>";
sOut += "<td>" +rP.sNameLast+ "</td>";
sOut += "<td>" +rP.sNameFirst+ "</td>";
sOut += "<td>" +rP.nAge+ "</td>";
sOut += "<td>" +rP.asChildren.length+ "</td>";
sOut += "</tr>";
}
sOut += "</table>";
return(sOut);
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (3)
Commented:
Open in new window
Author
Commented:=====================
One issue I hit on that "constructor issue" (and did not discuss in the article) is what happens when the caller skips a parameter in the middle of the list:
PersonRec("Rollins", "Dan", ,true, ['Ace','Spike'] ) ;
It seems to be a JavaScript compile-time syntax error to use two consecutive commas that way in a function call. I guess it's like with C++ where one needs to put the seldom-used parameters at the end. One could actually send in the string 'undefined', I suppose.
Commented: