What are the similarities and differences among the three styles of For loops in JS?

For reprinting, please indicate the source: Vineyard website Vineyard provides professional development tools, solutions and services to enable developers.
Origin: https://blog.bitsrc.io/3-flavors-of-the-for-loop-in-javascript-and-when-to-use-they-f0fb5501bdf3

 

The for loop is an essential grammar for learning any development language and may be used by all developers.It is so classic that every development language includes at least one version of the syntax for loops.However, there are three different looping syntaxes in JavaScript (four if you're more specific).

They are not used in exactly the same way, for example:

l. Classic For Loop Syntax

l For...of and For...in

l. A more dazzling version:.forEach

Next, I'd like to show you how and when these three grammars are used to achieve the best results.Okay, let's get started.

Classic For cycle

This syntax should be clear to all of us. In a for loop, you can define an internal counter, set interrupt conditions, and set flexible step strategies (usually incremental or decreasing).

The grammar is:

for([Counter Definition];[Break condition];[Step-by-step strategy]){
   //... 
    TODO
}

 

I'm sure you've written similar sentences before, even without my introduction, such as:

for(let counter = 0; counter < 10; counter++) {
console.log(counter)
}

 

Let's run it in Chrome and the results are as expected, but is the for loop just that?

 

You can think of the for loop as three expressions

for(
[An expression that executes only once at the beginning of a loop];
[The expression that each of these logical judgments must match];
[Loop an expression that is executed at each step]
)

 

The implication of this statement is that you can use multiple counters to execute a for loop or, without affecting the counters, execute code that needs to be executed each time in a step expression, for example:

for(let a = 0, b = 0; a < 10 && b < 100; a++, b+=10) {
   console.log(a, b)
}

 

We can go one step further and make it more applicable to real-world scenarios:

for(let a = 0, b = 0; a < 10 && b < 100; console.log("Your counter is now:", ++a, b+=2)){}

 

In addition, you can even replace an intermediate expression with a function call, as long as you remember that the return value of the function needs to be a Boolean or a value that can be converted to a Boolean, for example:

function isItDone(a) {
 console.log("Function called!")
 return a < 10
}

for(let a = 0; isItDone(a); a++) {
 console.log(a)
}

 

 

So how do you handle asynchronous code in the classic for loop?How can I make sure I don't fall into the asynchronous trap?

Let me introduce you to a new friend: async / await, which will make it easier and more controllable to work with asynchronous code, such as:

const fs = require("fs")

async function read(fname) {
    return new Promise( (resolve, reject) => {
        fs.readFile(fname, (err, content) => {
            if(err) return reject(err)
            resolve(content.toString())
        })
    })
}

(async () => {
    let files = ['file1.json', 'file2.json']

    for(let i = 0; i < files.length; i++) {
        let fcontent = await read(files[i])
        console.log(fcontent)
        console.log("-------")
    }
})()

For... in and For...of

They look very similar, but they are not the same type of cycle.

Let's try to explain them as briefly as possible:

For...in loops through enumerable properties of an object, that is, when your custom object is used as a hash table or dictionary, use For...in traverses them very easily.

Note, however, that the traversal order is executed in element order, so do not rely on cyclic order.

let myMap {
  uno: 1,
  dos: 2,
  tres: 3
}
for(let key in myMap) {
  console.log(key, "=", myMap[key]);
}

 

It looks simple, but remember, For...in can only traverse one entity object, and if it is convenient for a non-entity, such as traversing a string, the following will happen:

for(let k in "Hello World!") {
   console.log(k)
}

 

As you can see from the results, instead of traversing every letter, you traverse every attribute. As you can see, the traversed number is not useless, because "Hello World!"[1] can also return the corresponding letter.

Conversely, if you want to traverse each character, you need to use another variant: For...of

for(let char of "Hello World!") {
  console.log(char)
}

 

This looping seems to be more effective for string types, the same use case, because using this syntax, you can return the corresponding value in the element.So we can see from the above use cases that For...The content of an of traversal is the value of the object.

From the examples above, we can know that they traverse attributes and values one by one. So, if there is any way to get attributes and values at the same time, the answer is yes. With the entries method, attributes and values can be obtained at the same time, as follows:

let myArr = ["hello", "world"]
for([idx, value] of myArr.entries()) {
    console.log(idx, '=', value)
}

 

 

Finally, what happens when dealing with asynchronous code?The answer is, of course, the same as the for loop.

const fs = require("fs")

async function read(fname) {
    return new Promise( (resolve, reject) => {
        fs.readFile(fname, (err, content) => {
            if(err) return reject(err)
            resolve(content.toString())
        })
    })
}



(async () => {
    let files = ['file2.json', 'file2.json']

    for(fname of files) {
        let fcontent = await read(fname)
        console.log(fcontent)
        console.log("-------")
    }

    for(idx in files) {
        let fcontent = await read(files[idx])
        console.log(fcontent)
        console.log("-------")
    }
})()

 

Finally, let's summarize For in a short way.In and For...The difference between of

For...in -- Traversal properties

For...of - Traversal value

.forEach loop

This may be one of my favorite, just because I really like declarative syntax or the declarative way of writing code by command.

Furthermore, while the loop syntax above is also useful and has good use cases, forEach is useful when we need to focus on the data itself.

Regardless of the philosophical controversy aside, the.foreach method is another version of the for loop, but it is part of an array object that receives a function and an additional optional parameter to redefine the context of the function when it is executed.

For each element in the array, our function will be executed, and it will receive three parameters (yes, three, not one, because you're used to using it).They are:

  1. The current element being processed.
  2. The index of the elements, which has simplified our attempt to use for...Tasks implemented by the of loop
  3. The actual array being processed.Just in case you need to do something.

So let's look at a simple example:

a = ["hello", "world"]

a.forEach ( (elem, idx, arr) => {
   console.log(elem, "at: ", idx, "inside: ", arr)
})

 

Faster and easier, isn't it?

But you can see how we can easily use all the properties in a function.Here is an example of the second optional parameter you want to use in the foreach method:

class Person {
    constructor(name)  {
        this.name = name
    }
}

function greet(person) {
    console.log(this.greeting.replace("$", person.name))
}

let english = {
    greeting: "Hello there, $"
}
let spanish = {
    greeting: "Hola $, ¿cómo estás?"
}

let people = [new Person("Fernando"), new Person("Federico"), new Person("Felipe")]


people.forEach( greet, english)
people.forEach( greet, spanish)

 

By overriding the context of the called function green, I can change its behavior without affecting its code.

Finally, show that this method can also be used with asynchronous code, as shown in the following example:

const fs = require("fs")

async function read(fname) {
    return new Promise( (resolve, reject) => {
        fs.readFile(fname, (err, content) => {
            if(err) return reject(err)
            resolve(content.toString())
        })
    })
}

let files = ['file1.json', 'file2.json']

files.forEach( async fname => {
    let fcontent = await read(fname)
    console.log(fcontent)
    console.log("-------")
})

 

conclusion

That's all I want to share about loops in JavaScript. I hope you now have a clearer understanding of them and can choose your favorite loops based on this knowledge and our current actual needs.

Keywords: Javascript JSON Attribute

Added by ivalea on Fri, 27 Sep 2019 05:40:54 +0300