...

View Full Version : Why do prototyped methods of Array show up as members in individual arrays?



brothercake
12-20-2004, 10:44 AM
Here's some code to demonstrate how I came across this problem:


//prototype a custom method to Array
Array.prototype.something = function()
{

};

//prototype a method which is native
//to all test browsers except IE5.0
Array.prototype.push = function()
{

};

//data is a non-associative array
var data = [];

//therefore it has no length property
//so to find its length we have to iterate like this
var dataLen = 0;
for(var i in data) { dataLen++; }

//tell us the length of the array
alert(dataLen);

We get 1 in all browsers except for IE5.0, which returns 2. The differences makes sense, because both methods are custom to IE5.0, whereas push() is already native to the others.

The question is - why do prototyped methods show up at all, when native methods do not?

Jeff Mott
12-20-2004, 05:46 PM
//data is a non-associative array
//therefore it has no length propertyIn fact, non-associative arrays do have length. Associative arrays do not.

brothercake
12-20-2004, 07:07 PM
My bad - what I mean is, an array which is indexed with string keys

liorean
12-20-2004, 07:36 PM
The reason is that host methods in general are defined to not be enumerable, while all native methods are. That is in effect for the entire prototype chain, not just the object the method is placed upon. The member lookup scheme is indifferent to whether it's looking at direct members of the object or whether it's looking at prototype members. That way there is no need for building separate internal lookup methods for the two cases - there is only one case, in which you search an object for a member and if not finding it starting the same process with the next object in the prototype chain.

Also, all arrays have length, whether you use them as associative arrays or not. It's only objects, which can be used as hashtables/associative arrays if you wish, that do not have a length. Whether you use string keys or not is irrelevant. This can easily be shown by doing the following:
var
o=[true];
o['0']=false;
alert(o[0]); // => falseThe reason is that all lookups in JavaScript are by string keys, and if you don't use a string it will be converted to a string before doing the lookup.

brothercake
12-21-2004, 10:58 AM
Okay I'll buy that :) Apart from this:

Also, all arrays have length, whether you use them as associative arrays or not. .
They don't have a length property ...


var data = [];
data['foo'] = 'bar';
alert(data.length); //alerts 0

liorean
12-21-2004, 04:15 PM
They don't have a length property ...Perfect example, exactly the opposite conclusion to what I would have drawn from it. If it didn't have a length property it would have returned undefined.


var data = [];
data['foo'] = 'bar';
alert(data.length); //alerts 0
Object properties and array elements are fundamentally different. (Well, not in implementation but in how it looks from an outside perspective.) Adding an object property to an array naturally doesn't increment the length of the array, because you have not added an array element. Array elements are a subset of object properties on Array type objects, namely those object properties that have a numeric index. You cannot access object properties on an array using numeric index, so it makes no sense to add them to the length - that would break any looping through the array if you allowed it. JavaScript doesn't have any native Collection/Dictionary object (which is just that - a hashtable were all hashes are also accessible by numeric index), so if that's the feature you're looking for, you'll have to write the object for it yourself.

brothercake
12-21-2004, 10:59 PM
Gotcha. Now I understand :thumbsup:

What I really need is to be able to go "for(i in myarray)" and be confident that prototyped methods of Array which [may] exist in other [unknown] scripting are not included. But I can acheive that by checking each iteration with typeof, or further testing it as necessary, to determine if it's a member I'm interested in.

Thanks for your help, as ever :)

ca_redwards
06-07-2006, 11:48 PM
For my own convenience, I attached a few functions onto the Object.prototype...

// convenience functions
Object.prototype.write=function(){document.write(this);return this}
Object.prototype.alert=function(){window.alert(this);return this}
Object.prototype.status=function(){window.status=this;return this}

But then discovered that I couldn't simply walk the attributes of a generic object without bumping into my own function identifiers. To prevent that, I found that if I test a given attribute against an empty object, then I can determine which are pre-existing attributes and which are not...

$=function(x,json){
var elem=document.getElementById(x);
if(json)for(a in json)if(!{}[a])elem[a]=json[a];
return elem
};
_=function(x,json){
var elem=document.createElement(x);
if(json)for(a in json)if(!{}[a])elem[a]=json[a];
return elem
};

BTW: I use my $ function for manipulation of existing DOM objects and the _ function for creating new DOM objects. By passing a JSON (JavaScript Object Notation) parameter, I can very easily assign attributes and attach event handlers.


$('someElementID',
{'color':'red',
'onblur':function(){('ERROR: Invalid '+this.id+' value ['+this.value+']').alert();this.focus()}
}
);

liorean
06-07-2006, 11:57 PM
Boy, did you check the age of the thread you ressurected? :)



Oh, and if I were you I'd change
if(json)for(a in json)if(!{}[a])elem[a]=json[a]; to
if(json)for(a in json)if(json.hasOwnProperty(a))elem[a]=json[a];

That way it works for any type of object.

ca_redwards
06-08-2006, 12:03 AM
Boy, did you check the age of the thread you ressurected? :)



Oh, and if I were you I'd change
if(json)for(a in json)if(!{}[a])elem[a]=json[a]; to
if(json)for(a in json)if(json.hasOwnProperty(a))elem[a]=json[a];

That way it works for any type of object.

Do both (IE and FF) support that method?

liorean
06-08-2006, 12:48 AM
I'm not sure about ie5.0 or nn4 (haven't got them installed to test it), but I know op/moz/ie6w support it.

Kor
06-08-2006, 10:07 AM
hasOwnProperty() ... geee, I always thought that this method is an IE only, and I was too lazy to check it in other browsers ...

http://msdn2.microsoft.com/en-us/tz3t700w.aspx

Very useful, I would modify some of my codes with it.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum