3

Consider the following code:

var arr = [];
arr["abc"] = 1;
arr["bcd"] = 2;
console.log(arr.length); // outputs 0
arr["1"] = "one"; // notice the subscript content is in quotes
console.log(arr.length); // outputs 2
console.log(arr); // outputs [undifined, "one"]
console.log(arr["abc"]); // outputs 1

In the above program, I have defined the array arr which is first assigned with string indexes, so the array length stays 0. I read somewhere that when string value is used for subscript, the array object is treated as an ordinary object. So, I can understand if the length is zero (Should probably be undefined).

Then, when I use a subscript of "1", which should be of string type is taken as a Number and the length is incremented. Then when the array is printed there is a value of undefined for the index 0 and index 1 has the value "one" ( Note that the indexes "abc" and "bcd" are not shown when printed.

Finally, when I try to access the "abc" value, I get the value.

So my questions are the following:

  1. What happens when an array is assigned with a string index and why does the length remain the same?
  2. Does the javascript interpreter tries convert the index to a Number before using it?
  3. Where are the values of the array string indexes stored and why are they not shown when I try to print the array?
  4. Finally, can someone point me to a good article which explains the implementation details of javascript's features.

Thanks in advance.

anirudh
  • 4,116
  • 2
  • 20
  • 35

5 Answers5

6

This is an interesting question. JavaScript treats arrays and structures in similar ways.

var arr = [];

This created a new variable and set it to an empty array.

arr["abc"] = 1;

This created a property of arr called abc and assigned it the value 1. arr is now an array with a user-defined property.

arr["bcd"] = 2;

This created a second property of arr called bcd and assigned it the value 2. arr now has two user-defined properties.

console.log(arr.length); // outputs 0

The array still doesn't have any elements, so its length is zero.

arr["1"] = "one"; // notice the subscript content is in quotes

"1" evaluates to an integer and, since arr is an array (though it has some user-defined properties), it assigns "one" to the second (zero-based) element of the array.

console.log(arr.length); // outputs 2

arr[0] doesn't exist, but index 1 does, so the array has length 2.

console.log(arr); // outputs [undefined, "one"]

No definition was provided for index 0.

console.log(arr["abc"]); // outputs 1

Now we're accessing the user-defined property.

Thank you to Peter Flannery for providing the link to MDN's documentation on this.

Community
  • 1
  • 1
Paul Rowe
  • 778
  • 3
  • 10
  • 1
    I think pauls answer is right, So just to add the answer to your question number 4, https://developer.mozilla.org/en-US/docs/Web/JavaScript is a good place the implementation detail of javascript's features. – Peter Flannery Mar 05 '15 at 16:36
  • @PeterFlannery Should I incorporate that link into my answer? – Paul Rowe Mar 05 '15 at 16:38
  • [`arr[0]` is *not* back-filled](http://stackoverflow.com/q/1510778/1048572). That should be even apparent in the output, it'll be different when you do `arr[0] = undefined` – Bergi Mar 05 '15 at 16:38
  • @Bergi Definitely an issue with my choice of terminology. The element exists, but it doesn't have a value. What would be a better choice of terminology? – Paul Rowe Mar 05 '15 at 16:40
  • @PaulRowe it's all about the rules for the value of the `length` property; it has nothing to do with "empty" array properties. All that matters is that the `length` is one greater than the largest integer-valued property name. – Pointy Mar 05 '15 at 16:46
  • @PaulRowe Yes add it to your answer if you want. Going over to the other discussion regarding the Array item existence scenario, I disagree, an ```undefined``` array item is still counted in the ```arr.length``` property and is also outputted in ```JSON.stringify``` as null so ```var arr = []; arr[1] = 1; console.log(arr.length===2);``` means item 0 exists in the array regardless of being ```undefined``` – Peter Flannery Mar 05 '15 at 17:03
3
  1. JavaScript arrays are just a regular object that treat numerical indexes specially. When using strings as indexes, the object behaves like any other JavaScript object and adds them as properties on the object.

    When you use numerical indexes, the Array behavior kicks in.

    arr.abc = 1;
    arr.bcd = 2;
    arr[1] = 'one';
    
  2. Nope. Quite the opposite actually. Numbers are coerced to strings.

  3. The first two properties are stored as regular object properties. Printing an object doesn't typically print its properties, so you don't see them. You instead see [undefined, "one"] because you haven't assigned anything to arr[0] (so it's undefined).

  4. https://developer.mozilla.org/en-US/docs/Web/JavaScript

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • Your answer for 2 is wrong here. The "1" is auto-cast to a number for the purposes of the index. This is why it shows up when viewing the contents of the array. – seanmk Mar 05 '15 at 16:34
  • 1
    @seanmk: No, per spec everything is cast to a string, and then the array checks whether that string is numeric to decide whether it needs to do something about `.length`. (Of course that's not exactly how implementations do it) – Bergi Mar 05 '15 at 16:36
  • 2
    @seanmk - Actually, that's incorrect. Take a look at MDN: "The 2 in years[2] is coerced into a string by the JavaScript engine through an implicit toString conversion.": https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array – Justin Niessner Mar 05 '15 at 16:37
2

A good article which explains the implementation details of javascript's features? Of course the ECMAScript standard.

Especially, there is a paragraph explaining the behaviours of length.

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 own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.

Alex Lau
  • 1,687
  • 10
  • 17
0

Arrays are just objects in JavaScript, although a special kind of object.

  1. What happens when an array is assigned with a string index and why does the length remain the same?

The array object receives a new property.

var arr = [];
arr['hello'] = 'world'; // same as arr.hello = 'world';
arr.hello; // 'world'
// but 'hello' is not numeric, so arr.length is still 0
arr; // []
  1. Does the javascript interpreter tries convert the index to a Number before using it?

JavaScript always casts properties to String, so:

var arr = [];
arr[12] = 'test'; // same as arr['12'] = 'test';
arr[{}] = 'test2'; // same as arr['[object Object]'] = 'test2';
  1. Where are the values of the array string indexes stored and why are they not shown when I try to print the array?

The functions responsible for stringifying (such as Array.prototype.toString or JSON.stringify) or inspecting the array strip all non-numeric properties for you.

  1. Finally, can someone point me to a good article which explains the implementation details of javascript's features.

Too broad... here's one: https://developer.mozilla.org

Oleg
  • 9,341
  • 2
  • 43
  • 58
0

What makes Array instances interesting is the way property assignment implicitly affects the value of the length property. Array instances always have a length. When a property assignment is made with a property name that looks like an integer (an unsigned 32-bit integer), then the process of assigning the property value includes a check to see if the integer value of the property name is greater than or equal to the then-current value of length. If it is, then the length is increased to be one greater than the value of the property name.

Similarly, setting the length explicitly to an integer value will have the side effect of deleting any properties whose names look like unsigned 32-bit integers that are greater than or equal to than the updated length value. (The runtime won't let length be set to an invalid value.)

Otherwise, array instances are objects. A property assignment that involves a property name that does not look like an unsigned 32-bit integer value has no effect on the length property at all, and assignments to length have no effect on such properties. All enumerable array properties will show up in for ... in loops and in the return value of Object.keys().

The JSON.stringify() facility will only pay attention to the index properties of arrays (the properties whose names look like unsigned 32-bit integers).

Pointy
  • 405,095
  • 59
  • 585
  • 614