Lapys
Lapys

Reputation: 946

Weird Array Objects - JavaScript

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;

normalArray; // returns [1, 2]
normalArray.length // returns 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.: custom array)
var customArray = new (function MyArray() {
    this.__proto__ = Object.create(Array.prototype);
    return this
});
customArray.length = 0;

customArray.push(1);
customArray[1] = 2;

customArray; // returns [1, 1: 2]
customArray.length // returns 1

Not entirely sure what's going on here but some explanation will be much appreciated.

Upvotes: 0

Views: 506

Answers (3)

Saurabh Tiwari
Saurabh Tiwari

Reputation: 5151

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.

Upvotes: 1

Nimeshka Srimal
Nimeshka Srimal

Reputation: 8930

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

Upvotes: 1

Jack Bashford
Jack Bashford

Reputation: 44107

From what I can see, you have a problem with your function:

return this

This should be

return (this);

Just fixes any potential errors you might have. Another thing is you're not using the var keyword to declare customArray. These errors might be breaking your code.

Upvotes: 0

Related Questions