0

I have

b = [1, 2, 3, [4, 5], 6];

b.forEach((value, index) => {
    if (Array.isArray(value)) {
        value.forEach(element => element += 2)
    }
    else {
        value += 2;
    }
    console.log(`The value at ${index} is ${value}`);
})

And I'm wondering why this is logging

The value at 3 is 4,5

Instead of

The value at 3 is 6, 7

I thought I'd accessed the inner array by checking if the value is an array, and then I did another .forEach loop to access each element of that inner-array?

Trying to fully understand .forEach() in JS. Thanks!

3
  • After the loop, do you expect b[0] to be 1 or 3? (Not the output, the value in b after the loop has completed.) Commented May 29, 2019 at 14:27
  • 1
    @T.J.Crowder I wasn't trying to alter the original values of the array, just the output values. So in this case I was just expecting b[0] to still equal 1. Commented May 29, 2019 at 14:30
  • 1
    Though seeing how to alter the values of the original array is also helpful. Commented May 29, 2019 at 14:31

2 Answers 2

3

There are two reasons:

  1. forEach completely ignores the value you return from its callback

  2. You never do anything to update value

If you want to modify value, you'd either do this:

value = value.map(element => element + 2);

...which creates a new array and assigns it to value; note that b is completely unaffected. (This is just like your value += 2 in the other branch, which also doesn't affect b at all.) Live example:

const b = [1, 2, 3, [4, 5], 6];

b.forEach((value, index) => {
    if (Array.isArray(value)) {
        value = value.map(element => element + 2);
    }
    else {
        value += 2;
    }
    console.log(`The value at ${index} is ${value}`);
})
// Just to show that `b` is unaffected:
console.log(`b[3] = ${b[3]}`);

Or this:

value.forEach((element, index) => {
    value[index] = element + 2;
});

...which changes the original array (inside b), which doesn't match the else branch (which doesn't update b). Live example:

const b = [1, 2, 3, [4, 5], 6];

b.forEach((value, index) => {
    if (Array.isArray(value)) {
        value.forEach((element, index) => {
            value[index] = element + 2;
        });
    }
    else {
        value += 2;
    }
    console.log(`The value at ${index} is ${value}`);
})
// Just to show that `b` is modified:
console.log(`b[3] = ${b[3]}`);

But, if you want to modify b, you should probably do it consistently. Kobe posted how you'd do that with map, which creates a new array and is often what you want. If you wanted to update the existing array instead, then:

const b = [1, 2, 3, [4, 5], 6];
for (const [bIndex, value] of b.entries()) {
    if (Array.isArray(value)) {
        for (const [vIndex, entry] of value.entries()) {
            value[vIndex] = entry + 2;
        }
    } else {
        b[bIndex] = value + 2;
    }
}
console.log(`b = ${JSON.stringify(b)}`);

...but Kobe's map solution is usually what I'd reach for unless I had a good reason to update in place.

Sign up to request clarification or add additional context in comments.

Comments

1

You are editing the property, not the value, but then you are not storing the new property anywhere. You should reference the value you are logging, not the properties:

b = [1, 2, 3, [4, 5], 6];

b.forEach((value, index) => {
    if (Array.isArray(value)) {
        value.forEach((element, i) => value[i] += 2)
    } else {
        value += 2;
    }
    console.log(`The value at ${index} is ${value}`);
})

Should you want to avoid writing this, you should use map to return a new array with the modified values:

b = [1, 2, 3, [4, 5], 6];

b = b.map(value => Array.isArray(value) ? value.map(el => el + 2) : value + 2)

console.log(b)

4 Comments

This modifies b when the entry is an array, but not when it isn't. The OP didn't tell us what they want us to do, but given the value += 2 in the else, probably best not to modify b in the if branch either.
Ah, yes, you're correct. I'll leave it as is, but if it's an issue ill remove it.
They wanted to leave b alone, but this is still helpful for others.
@T.J.Crowder Cheers mate, I edited my answer so as not to mutate the original array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.