'Change value of a variable inside foreach loop? Make it available outside the loop

I'm setting an initial flag then doing a foreach which changes the flag to a different value but outside the foreach loop I still see the original flag. As if nothing changed. But it did change inside the foreach loop

The value is only changed inside the foreach loop, but not outside of it..

I saw a number of similar questions but they all deal with the actual array values, in this case it's a simple variable outside of the foreach loop.

    var arr = ["one"];

    var str = 0;

    arr.forEach(function(part){

        if(part == 'one') {
            var str = 1;
            console.log('str changed to: ' + str);
        }

    })

    console.log('str is now: ' + str);

This will return

str changed to: 1
str is now: 0

Based on my PHP logic above should return "str is now: 1", why does it have the original value of 0?



Solution 1:[1]

This is because you are re-declaring the variable with var in the loop instead of just updating/setting it. Re-declaring it wipes out the earlier variable of the same name from the previous loop iteration and hides the one from the function in the higher scope. It establishes a new one instead of just updating the value in the existing one.

var arr = ["one"];
var str = 0;
arr.forEach(function(part){
 if(part == 'one') {
   str = 1;
   console.log('str changed to: ' + str);
 }
})

console.log('str is now: ' + str);

Solution 2:[2]

The problem is that you're declaring a new str variable inside of forEach. Just drop the var and it will work.

var arr = ["one"];
var str = 0;

arr.forEach(function(part) {
  if (part == 'one') {
    str = 1; // Notice the lack of var
    console.log('str changed to: ' + str);
  }
});

console.log('str is now: ' + str);

Solution 3:[3]

Just as an additional answer that wants to suggest a different way to do what you are doing with forEach:

Array.prototype.some() does a good job here. It tests if any array element satisfies the condition in the callback function you pass to it.

let arr = ["two", "one", 7];
let str = 0;

str = arr.some(part => part === 'one') ? 1 : str;

console.log('str is now: ' + str);

Solution 4:[4]

So I had this challenge where I needed to await a query in a forEach loop and it was giving me issues. So I just had to use a for...of instead of forEach.
let answers = [
    {
        questionId: "questionId1",
        answer: "answer1",
    },
    {
        questionId: "questionId2",
        answer: "answer2",
    }
]

Now I used a forEach loop and I needed to query inside the forEach loop. So what I did was use a for of instead of forEach like

Previously

let score = 0
let question
answers.forEach(async(obj) => {
    // Query obj.questionId here
    question = await Question.findOne({id: obj.questionId)
    if(obj.answer == question.answer){
        score += 1
    }
})
console.log(score)

In my case, the above didn't work because the score being logged above prolly got executed before the response from the question queries were received.

Now
let score = 0
let question
for(obj of answers){
    question = await Question.findOne({id: obj.questionId)
    if(obj.answer == question.answer){
        score += 1
    }
}
console.log(score)
In the end I was happy and that's all I needed to do. So why not use for of instead of forEach and be happy too. Lol

Solution 5:[5]

buddy you are doing the same mistake I was making don't initialize variable inside foreach loop.

i.e. use str = 1; instead of var str = 1;

inside if of your for loop

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Mike Cluck
Solution 3
Solution 4 2mighty
Solution 5 Sanket