Reviewing the technical side of loops... [is this right?]

Loop: the conditional, finite, repetitive execution of code.

So, there is obviously a lot here that is going to transcend my intermediate understanding, specifically relating to the actual lower-level iteration process, but I just want the basics:

const obj = {["a Sandy"]: "open shore", type: 5};

for (k in obj) {
 console.log(k);
}

Right,

now, the variable k is declared and initialized, then assigned to 0 [first index]. When you console.log you see the output of k is the first key, so for the first iteration of this loop it must have evaluated obj[k], yes? (?)

this is implicit behavior, so it confuses me. it occurs to me a lot of abstraction is at play - which i dislike.

So, the in operator returns true or false, so am I right to assume that when the iteration begins each time, that the loop will break if the operator returns false? (?) I am trying to understand exactly how the “condition” part of this loop resolves to false to end the statement’s execution… but I am not sure. I can also see it ending implicitly if the current k value is greater than obj.length.

The k in obj is kind of syntax sugar for k of Object.keys(obj).

The k is initialized in that for loop constructor, but it’s not contained there. Prefer for (let k in obj) to scope it down.

must have evaluated obj[k]

Not really, you just have the k. To grab your value, you’ll need to do the obj[k] lookup.

this is implicit behavior

No exactly. Again, it’s really just syntax sugar.

So, the in operator returns true or false

Not following, I’m afraid. No?

You seem to be assuming this is a for(init;stop condition;process) kind of affair. It’s not really that kind of loop.

It’s a lot more like a forEach. e.g:

Object.keys(obj).forEach(k => console.log(k))
1 Like

Thanks mate, fumbling.

syntax sugar for **k of Object.keys(obj).**

That makes way more sense to me… So, just to use that as an example, that means k is assigned to the currently indexed key of the obj array, right?

I am trying to visualize exactly what occurs in that case, during each iteration. That is where I am struggling… I think I should sit down with some pen/paper and write out the evaluation order. I don’t understand what is facilitating the iteration - because nothing is explicitly being iterated. From what I can tell unlike a traditional for loop with a counter variable I see no counter variable

What also bewildered me slightly is that the in operator returns true or false, so I am thinking about how in would interface with the for keyword.

In JavaScript, Arrays are Object, which is why we were told to never use the in operator on arrays because it can expose other attributes of the array object that are not meant to be exposed. The of operator was introduced so the arrays would have a membership operator that doesn’t cross the line on Array objects that in does.

of has not been around for that long, if you’re my age. It may have always existed if one started coding in 2005 or later. The key word is membership. Both in and of refer directly to the values referenced, not their index position in the array.

Bottom line, where in is used to test membership, a special purpose operator, it can also (more typically) be used to work with for in iteration of an object’s key set. Given the dual purpose utility, it can also be used in while loops:

x = 'somekey'
while (x in obj) {
    // loop for some time until some action removes the key/value
}

That’s just theory so don’t look for practical value, only demonstrative.

When thinking of in or of we’re not considering their position, which in the case of in doesn’t matter or have any bearing since there is no discernable position in an object. of in a sense is wired the same way. We need to poll the array for the index of a value, and then can only rely on it to give us the first position since arrays can have multiple repeated values. Objects cannot have any repeating keys.

It really only becomes important to know a value’s position if we wish to mutate it. A value cannot be mutated in an of loop. Sure we have the value in memory (the iteration variable) but we have no direct binding to its location in memory, only its occurrence within the list of items.

Say we have a list of fruits, unordered in an array. We wish to find where apple is positioned in the array, notwithstanding there may be more than one ‘apple’. We want to change that to ‘banana apple’.

fruits[fruits.indexOf('apple')] = 'banana apple'

Eg.

 > fruits = ['banana', 'pear', 'orange', 'apple', 'grapefruit']
<- (5) ['banana', 'pear', 'orange', 'apple', 'grapefruit']
 > fruits[fruits.indexOf('apple')] = 'banana apple'
<- 'banana apple'
 > fruits
<- (5) ['banana', 'pear', 'orange', 'banana apple', 'grapefruit']
 >

Fun fact

We in the Prairies used to refer to ‘Golden Delicious’ by that moniker. I didn’t just make it up.

Awesome reply, thank you… it explained a lot.

What finally helped me understand loops was thinking of each loop as a person taking “steps” to an intersection, each “step” representing a single iteration, and the intersection itself representing the false state - ensuring the loop is finite.

for in and for of escaped my understanding because a lot of abstraction does take place behind the scenes - namely the conversion of the non-enumerated Object to an iterable Array, furthermore what exactly is actually iterating the loop to a false state remains a mystery to me, but how you explain each loop as ultimately accessing the value of an array now makes sense to me because of Object.keys(); although, it does seem counter-intuitive that in order to access the keys of obj - you must step through an array’s indexes.

What facilitates the actual iteration process in a for in or for of eludes me still, but I will look into it. I am thinking maybe a basic stepper variable exists behind-the-scenes which will break the loop when array.length is exceeded - the same variable being used to access the values.

1 Like

Objects are akin to a lookup table. Since we know the keys make up a set (no duplicates, no order) once we find the key we are looking for it is then possible to poll its associated value. To my mind, Object.keys() as a method might well be iterating over the set, not an array, for optimization purposes. What really matters for our purposes is less how it does this work in the background and more what it promises out front for us to be able to depend upon.

obj = {
  1: 'one',
  2: 'two',
  3: 'three'
  4: 'four'
}
for (let key in obj) {
    console.log(obj[key])
}
one
two
three
four

Now let’s demonstrate how an Array is an Object:

for (let key in fruits) {
    console.log(key, fruits[key])
}
0 banana
1 pear
2 orange
3 banana apple
4 grapefruit

Make sense?

Yup - that never escaped me; Arrays being Objects is something you are forced to understand once you start calling Array methods on them.

Butttttt. and this is a big but. I still feel it’s important to understand what is happening behind-the-scenes. Object.keys() might convert the Object to a generic shallow Array, and a for in keyword combination might possess unique functionality to enable iteration over that array, but nether of these adequately explain how the iteration process happens internally. There is no discernible stepper, condition, or even an initializer. All we see is an abstraction and we take advantage of its behavior.

1 Like

js for in and for of behind the scenes - Google Search

If I attempt to explain in any greater detail… Well, we know how that would go. The above serp should have lot of juicy tidbits and techspeak on a whole range of subjects relating to behind the scenes.

Something to keep in mind is that the engine is not the same in all browsers, only promising to comply with ECMAScript specifications. Chrome and Safari use the V8 engine, Firefox has there own, Edge has their own which might actually be a fork of the V8, but I’m not sure. At my age there is not much sense reading up on this stuff, especially since I am now more into reading Geology, and read less and less about code as time progresses. What the language promises and how to implement those promises is enough for me.

Hope you find what you’re looking for and will report back to this topic once you have some details to share. I’d love to hear what you find.

2 Likes

gotcha. sorry if i came off as pretentious… i actually am just interested. i know that JavaScript is a high-level language and the entire language itself could be described as an abstraction - so i just feel slimy relying on even more abstraction… i seem to have found something, but it is admittedly a very advanced topic for a noob like myself

1 Like

Not at all. If you did, then I induced it, perhaps. Needless to give it a second thought. I was hoping you would come upon a more technical discussion of iterables, iterators and generators, the latter two only coming into the language in ES6, if I’m correct. We didn’t have them in ECMAScript 5.

Another thing to bear in mind is that the JavaScript engine itself is probably written in C++ or C# for Edge. It could well be that there is no real JavaScript running in the parsing and byte coding stages (don’t know). There is an extreme amount of optimization at that level. It could be a C iterator that gets finally compiled for execution.

Also, think of the data. It is constrained and the system knows the size of the structure. Iteration could be recursive until end of data, for all we know. There is a unit on iterators in the Learn JavaScript module so if you’ve skipped that module, maybe spend the weekend going through it, or if you are in that module, pause from this pursuit, carry on and come back to this question when you’ve reached that unit.

Bottom line, I’m glad you are brave enough to ask this type of question, and willing to chase down some of the reading. Now you know it is there, put it on your long term reading list and take it up when you’ve gotten real comfortable with the language, in general. Happy trails!


One final correction: I meant to write 2015, not 2005.

1 Like