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.
-
is it quiz?????Nina Scholz– Nina Scholz2016年10月17日 11:37:28 +00:00Commented 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.zozo– zozo2016年10月17日 11:38:29 +00:00Commented Oct 17, 2016 at 11:38
-
var arr = new Array(15); console.log(arr); This gives me [] . Not what you mentioned.Netham– Netham2016年10月17日 11:42:16 +00:00Commented Oct 17, 2016 at 11:42
-
The logged result change depending on the browser's JS engine.Redu– Redu2016年10月17日 11:43:36 +00:00Commented Oct 17, 2016 at 11:43
-
Yup... After Netham comment I checked in chrome and got his result. In ff it gives mine.zozo– zozo2016年10月17日 11:44:38 +00:00Commented Oct 17, 2016 at 11:44
2 Answers 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
5 Comments
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.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