0

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.

7
  • 1
    stackoverflow.com/questions/34801251/… probably related Commented Aug 28, 2018 at 4:07
  • Thanks, but the question from the link 'stackoverflow.com/questions/34801251/…' is not entirely related. It asks about inheritance of the Array prototype by custom objects; Which is not the question of why adding elements (in different ways) to custom arrays & normal arrays seems kinda dodgy. Commented Aug 28, 2018 at 4:16
  • 1
    "Up to and including ES5 there is no way to cleanly extend Array in the usual constructor-prototype way without losing functionality, instead you have to add properties to an Array instance" A custom array would be an extension of Array would it not? Commented Aug 28, 2018 at 4:19
  • Hmm, you do have a point there. And yes, a custom array would basically be an extension of 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? Commented Aug 28, 2018 at 4:25
  • 1
    The accepted answer of the question that i linked ;). You can find similar reports by looking up subclassing or extending javascript arrays using your favourite search engine Commented Aug 28, 2018 at 4:27

2 Answers 2

1

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 :)

Sign up to request clarification or add additional context in comments.

Comments

1

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

"Remember the 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.