JavaScript is a neat little scripting language and does the job it is intended for very well. The prototype system is very useful too, but has one major drawback. First, however, a very quick primer on how objects are made in JavaScript and what prototyping is.
This code creates a FooBar object in the variable MyObject with 2 members: Member1=5, and AnotherMember='Blah' .
function FooBar(ExampleArgument)
{
this.Member1=ExampleArgument;
this.AnotherMember='Blah';
}
var MyObject=new FooBar(5);
Now both MyObject and SecondObject have a member NewMember with value 7, which can be changed easily for both objects like this:
FooBar.prototype.NewMember=7;
var SecondObject=new FooBar();
FooBar.prototype.NewMember=9;
The way to detect if an object has a member is to use the in function, and then to determine if the member is prototyped, the hasOwnProperty function is used. For example:
'NewMember' in MyObject; //Returns true
MyObject.hasOwnProperty('NewMember'); //Returns false
'Member1' in MyObject; //Returns true
MyObject.hasOwnProperty('Member1'); //Returns true
'UnknownMember' in MyObject; //Returns false
MyObject.hasOwnProperty('UnknownMember'); //Returns false
This would output:
for(var i in MyObject)
console.log( i + '=' + MyObject[i].toString() ); //console.log is a function provided by FireBug for FireFox, and Google Chrome
Member1=5
AnotherMember=Blah
NewMember=9
This would output:
for(var i in MyObject)
if(MyObject.hasOwnProperty(i))
console.log(i+'='+MyObject[i].toString());
Member1=5
AnotherMember=Blah
This isn’t too bad if you are using prototyping yourself on your objects, but sometimes you might make objects that you wouldn’t expect to have prototypes. For good coding practice, you should really do the prototype check for every foreach loop because you can never assume that someone else will not add a prototype to an object type, even if your object type is private. This is especially true because all objects inherit from the actual Object object including its prototypes. So if someone does the following, which is considered very bad practice, every foreach loop will pick up this added member for all objects.
Object.prototype.GlobalMember=10;
This function will search for the first member that contains the given value and return the member’s name.
Object.prototype.indexOf=function(Value)
{
for(var i in this)
if(this.hasOwnProperty(i) && this[i]===Value)
return i;
return undefined;
}
It would be really nice if “for(x in y)” only returned non-prototype members and there was another type of foreach loop like “for(x inall y)” that also returned prototype members :-\.
for(var i=0;i<ArrayObject.length;i++)instead of
for(var i in ArrayObject)loops. Also, in my own code, I often add the following because the “indexOf” function for Arrays is not available in IE, as it is not W3C standard. It is in Firefox though... but I’m not sure if this is a good thing, as it is not a standard.
//Array.indexOf prototype
if(Array.prototype.indexOf==undefined)
{
function ArrayIndexOf(SearchIndex)
{
for(var i=0;i<this.length;i++)
if(this[i]==SearchIndex)
return i;
return -1;
}
Array.prototype.indexOf=ArrayIndexOf;
}
I’m not going to go into how JavaScript stores the prototypes or how to find out all prototype members of an object, as that is a bit beyond what I wanted to talk about in this post, and it’s pretty self explanatory if you think about it.