Arrays are quite something in JavaScript when compared with other programming languages and it's not without its full set of quirks.
Including this one:
// Making a normal array.
var normalArray = [];
normalArray.length = 0;
normalArray.push(1);
normalArray[1] = 2;
console.log(normalArray); //= [1, 2]
console.log(normalArray.length); //= 2
So yes, the above is how we all know to make arrays and fill them with elements, right? (ignore the normalArray.length = 0 part for now)
But why is it that when the same sequence is applied on an object that's not purely an array, it looks a bit different and its length property is off by a bit?
// Making an object that inherits from
// the array prototype (i.e.: a custom array)
var customArray = new (function MyArray() {
this.__proto__ = Object.create(Array.prototype);
return this
});
customArray.length = 0;
customArray.push(1);
customArray[1] = 2;
console.log(customArray); //= [1, 1: 2]
console.log(customArray.length); //= 1
Not entirely sure what's going on here but some explanation will be much appreciated.
2 Answers 2
This may not be the perfect answer, but according to my understanding of Javascript arrays, they are a little bit different than usual objects. (Mainly due to the fact that it maintains a length property, and Objects don't).
So if we take your code for an example:
var normalArray = [];
This is the right way to create an array in Javascript. But what about the below one?
var customArray = new (function MyArray() {
this.__proto__ = Object.create(Array.prototype);
return this
});
Are they same? Let's see..
Array.isArray(normalArray); // true -> [object Array]
Array.isArray(customArray); // false -> [object Object]
So it is clear that although you inherit from the array prototype, it doesn't really create an object with Array type. It just creates a plain JS object, but with the inherited array functions. That's the reason why it updates the length when you set the value with customArray.push(1);.
But since your customArray is only a regular object and for a regular JS object, [] notation is used to set a property, it doesn't update the length (because Objects don't have a length property)
Hope it's clear :)
Comments
The array you are trying to create is not a pure array (as you are perhaps aware). Its basically a JavaScript object and is supposed to behave like an object.
While treating an object like an array, its up to you to maintain all it's array like features.
You specifically have to assign a length property to it and you did it correctly.
Next, the push method from Array.prototype is supposed to insert an element to the array and increment the length property (if any), so it did increment 0 to 1. There you go, the length now is 1.
Next you used the literal notation of property assignment to Object, which is similar to something like customArray['someProperty'] = 1.
While using literal notation, no method from Array.Prototype is being invoked and hence the customArray object never knows that it has to behave like an Array and its length property remains unaffected. It simply behaves like an object and you get what you got.
Remember the length is just a property on Array class and this property is appropriately incremented and decremented by every method on Array.
Note: Array like objects are not recommended and its up to you entirely to maintain the index and other Array stuff for such objects.
1 Comment
length is just a property on Array class and this property is appropriately incremented and decremented by every method on Array." - that is not quite right. length is an instance property of arrays, and it does automatically change its value when index properties are assigned.
Arraywould it not?Array. Does this really propose that there is no way to invalidate this odd behavior of arrays..? You quoted something, can I see where you got the reference there?