0

I find the following behavior of js a bit strange and can't find out why this is happening.

Lets assume the following code:

var arrayName = new Array(15);
console.log(arrayName);

This will output [undefined, undefined, undefined, ... ] (undefined 15 times).

Now lets use the following code:

var arrayName = new Array(15).fill();
console.log(arrayName);

Since no argument was supplied for fill, this will output (as expected) [undefined, undefined, undefined, ... ] (undefined 15 times).

Now lets add a loop through the array (using the for in format, not the incremental one):

var arrayName = new Array(15);
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}

This will output nothing (not really why I would expect - I would expect numbers from 0 to 14)

Now lets use the code with fill:

var arrayName = new Array(15).fill();
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}

This will output 0, 1, 2, ..., 14 (what I would expect in both cases).

So... why the difference?

I think the indexes are not created in the first case (but still the undefined elements are output... why?). Is this a language inconsistency or is some logic behind it?

P.S. Move mouse over blank boxes to see content.

5
  • is it quiz????? Commented Oct 17, 2016 at 11:37
  • Nope.. I really don't get why that is happening. If it was quiz I would put it on codegolf :). I added spoilers so I don't influence thoughts with my personal opinions. Is not a real practical question (I just add fill when I need it), but I would still like to understand the logic. Commented Oct 17, 2016 at 11:38
  • var arr = new Array(15); console.log(arr); This gives me [] . Not what you mentioned. Commented Oct 17, 2016 at 11:42
  • The logged result change depending on the browser's JS engine. Commented Oct 17, 2016 at 11:43
  • Yup... After Netham comment I checked in chrome and got his result. In ff it gives mine. Commented Oct 17, 2016 at 11:44

2 Answers 2

2

Basically: DONT USE FOR.IN ON ARRAYS! : http://ilikekillnerds.com/2015/02/stop-writing-slow-javascript/

for.in is for objects. Even MDN states this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

The array is created and it has some indexes, but since there isn't any real data (undefined), then why would there be any keys?

//The difference is in enumerable keys:

console.log(Object.keys(new Array(15))); //Produces no keys since no data is allocated
console.log(Object.keys(new Array(15).fill())); //Produces 15 keys

//What you probably want is to loop through the allocated places in the array, not the keys of it:
for(var i = 0; i < new Array(15).length; i++) {
  console.log(i)
}

Why is this?

Have you ever tried Object.create?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

//Allocating a new object
var test = Object.create({}, {
  p: {
    value: 42
  }
});

//Logging object... but where is p?
console.log("where is p?",test);

//there it is :)
console.log("there it is",test.p);

//Lets try that again
test = Object.create({}, {
  p: {
    value: 42,
    enumerable: true
  }
});

//Logging object... and there is p
console.log("All good",test);

//New object values are non-enumerable by default. Also on Arrays

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

5 Comments

So what you say is that you can have an array with length, but without keys?
Basically yes. That is what my snippet is demonstrating by calling Object.keys on the array. When you run a for..in loop, you are basically running a standard for loop, but on the keys, so that is why it won't work.
Yeah I know how it works internally (also know what the good practices are - and when to ignore them :) - it was a theoretical question)... but I always thought the length property is strictly related with the number of existent keys. Apparently is independent then.
It has to do with how objects are created in JavaScript. In short they are non-enumerable unless specifically told to be otherwise. If you create an array of basically nothing, then the indexes wont be enumerable. Length and keys are related, but keys aren't necessarily enumerable.
THAT is the answer I was looking for (I know I accepted earlier but I did because I filled in the gaps :) ). I generally use a generator function for objects and that makes attributes enumerable by default. I didn't know by default they are not enumerable (and since Arrays are basically a subset of Object did not know their keys may not be enumerable by default), hence my confusion.
1
var arrayName = new Array(15);
console.log(arrayName);
for (var i in arrayName) {
    console.log(i);
}

Let's see what happened in the above case.

var arrayName = new Array(15);

If the only argument passed to the Array constructor is an integer between 0 and 232^-1 (inclusive), this returns a new JavaScript array with length set to that number.

So this is what you got in the above case. So it's an empty array with length set to 15. Now you used for in loop,which iterates over enumerable property, and a different property name is assigned to variable i on each iteration

console.log(arrayName.propertyIsEnumerable('length'));

This returns false, so the array you have has no enumerable property and is an empty array. So you get nothing.

Now in the second case, since you used fill(), but you passed no value as the first argument, which is used to populate the array. Since you passed no value, the whole array was filled with undefined, with array indexes defined till the length of the array. ( See the constructor for fill here https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill)

Also note "Array indexes are just enumerable properties with integer names".

Now the for in loop iterated over the array index property, and printed the value of them which prints 0-14.

For more understanding, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Comments

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.