Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In-operator before and after for-in loops

I'm fairly new to Javascript and was trying to figure out exactly how the for...in loop works based on how the in operator works.

This cleared up the confusion.

However, I'm now confused as to why the in operator returns false in all scenarios besides the very last one.

It looks like the for...in loop is creating the key keyTest in obj with the value of its last iteration.

Is my understanding correct? Do for...in loops create key/values in the object they iterate over when used to go through all of an objects keys?

If so any help on understanding would really help.

var keyTest, obj = {}
keyTest in obj; // false
for(var keyTest in obj) { obj[keyTest] };
keyTest in obj; // false

obj = { a : 1, b : 2 };
keyTest in obj; // false
for(var keyTest in obj) { obj[keyTest] };
keyTest in obj; // true
obj[keyTest] // 2
like image 729
Ro_double_b Avatar asked May 11 '16 23:05

Ro_double_b


2 Answers

Do for...in loops create key/values in the object they iterate over when used to go through all of an objects keys?

No, but they assign keys to the iteration variable (var keyTest in your case). And that's why your examples produce the results you see.

// keyTest = undefined (initialisation of the hoisted variable)
var keyTest, obj = {} // keyTest === undefined
keyTest in obj; // keyTest === undefined
for(var keyTest in obj) { obj[keyTest] }; // `obj` is empty and `keyTest` stays what it is
keyTest in obj; // false // keyTest === undefined

// keyTest = undefined (initialisation of the hoisted variable)
obj = { a : 1, b : 2 }; // keyTest === undefined
keyTest in obj; // keyTest === undefined
for(var keyTest in obj) { obj[keyTest] }; // keyTest = "a", keyTest = "b"
keyTest in obj; // keyTest === "b"
like image 80
Bergi Avatar answered Nov 18 '22 02:11

Bergi


It's hoisting issue. There is no block-level scope in es5, so your keyTest variable is hoisted and declared at the beginning of the scope (function or global, it depends on where you run your code).

So var keyTest is not block variable, but scope variable, accordingly it refers to the same variable in every line of your code where it's used in this scope. And it's a reason why your for loop assigns last value of iteration to this variable.


If to talk about your example, the reason why you've got two different results is that in first example you have no keys in your obj, so for loop won't do any iteration, accordingly will not assign any value to your keyTest so it'll be still undefined.


But for example es6 has block-level variables. So if you change var to let (block-level variable declaration keyword) in your for loop and run this code in es6-compatible environment, you will have different output. Maybe this will help you to understand what is going on.

//es6 code
var keyTest;
obj = { a : 1, b : 2 };
keyTest in obj; // false
for(let keyTest in obj) { obj[keyTest] };
keyTest in obj; // false
obj[keyTest] // undefined
like image 2
Yuriy Yakym Avatar answered Nov 18 '22 04:11

Yuriy Yakym