View Full Version : Does IE not allow Array inheritence?
wyrd33
03-18-2006, 01:28 AM
I have a custom object that inherits from an Array(), and it works fine in FireFox. Unfortunately Internet Explorer goes a little bonkers.
<script language="JavaScript">
function People()
{
// Nothing.
}
People.prototype = new Array();
var p = new People();
p.push("Frank");
p.push("Tom");
alert(p.length); // Displays 0 in IE.
</script>
The alert displays 0 in IE, but 2 in FireFox.
Am I missing something?
liorean
03-18-2006, 02:33 AM
Array inheritance is suppored, as evidenced by that push works. However, the special behavior of the length property is, in difference to the actual length property, not a property or method and is thus not inherited.
This should be the common behavior for all ECMAScript 3 compatible scripting engines.
wyrd33
03-18-2006, 06:29 AM
Array inheritance is suppored, as evidenced by that push works. However, the special behavior of the length property is, in difference to the actual length property, not a property or method and is thus not inherited.
This should be the common behavior for all ECMAScript 3 compatible scripting engines.
There's more going on here than the class not inheriting the length property, as the above script works perfectly in FireFox (the alert displays 2). Continuing with the script above:
<script language="JavaScript">
function People()
{
// Nothing.
}
People.prototype = new Array();
var p = new People();
p.push("Frank");
p.push("Tom");
alert(p.length); // Displays 0 in IE.
alert(p[0]); // Displays Tom in IE (note, this is WRONG).
alert(p[1]); // Displays undefined in IE (WRONG!).
alert(p.toString()); // Displays nothing in IE.
</script>
I added a few more alerts down on the end. As you can see, p[0] displays the last item put into the array via push(). This is most definitely not the behavior you'd expect. The output should be Frank for p[0], not Tom. If my class is not going to inherit the special features of the Array class, then I might as well not bother. What's the point?
I've resorted to just encapsulating the Array (this.list = new Array();) inside the People object. I can then do everything I want via People.list, but it's not what I wanted. People has a list of people? People IS a list of people. Not correct OOD, but oh well.
liorean
03-18-2006, 10:11 AM
Still, ie is not doing anything I don't expect from it here. The special behavior of arrays when it comes to how member names that can be turned into positive integers are treated, with regard to the length property etc are not part of the prototype inheritance scheme. First of all, Let me quote the part of the ECMAScript 3 specification that tells us this type of behavior should not be inherited:15.4 Array Objects
Array objects give special treatment to a certain class of property names. A property name P (in the form of a string value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 232−1. Every Array object has a length property whose value is always a nonnegative integer less than 232. The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to properties of the Array object itself and is unaffected by length or array index properties that may be inherited from its prototype. [emphasis mine]
Well, actually the push method is defined in such a way that it should increment the length property, so that part should work, and that ie does get wrong. But array behavior hinging on the special treatment of members that can be converted to positive integers should not be inherited.
The way to best create a good array-alike object in JavaScript is to just use an array. Like thisfunction createPeopleList(arr){
if(typeof arr != 'object')
arr=[];
arr.property=blah;
...
return arr;
}Object orientation in JavaScript is not very similar to class based object oriented languages. If you can avoid to create new "classes" and use native types, then you should. There is very little gain in extending native types, and inheritance is performance wise rather expensive, which is quite different from the typical class based language.
There is only one situation where I would say using the JavaScript inheritance is worth it, and that is if you have an object that will need run time extension of the prototype. If you just need static inheritance, then the method used in the function above works better.
... I should only add the fact that the moment you have called a function and used a prototype, you have created an object. object's elements are unsorted, unlike the classical arrays elements which are sorted collections.
There is very much alike with:
<script type="text/javascript">
var p={
0:'Frank',
1:'Tom'
}
alert(p.length)//is undefined, as the elements in object are unsorted
//to circle, you may only:
for(param in p){
alert(param+'|'+p[param])
}
</script>
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.