0

Why does the first block of code work (with for loop) and the second doesn't (with forEach)?

(I am trying to make all words start with an uppercase letter in a string)

1)

function capitalize(str){
  let wordList = str.split(" ");

  for (i = 0; i < wordList.length; i++){
    wordList[i] = wordList[i][0].toUpperCase() + wordList[i].substring(1);
  };

  return wordList.join(' ');
};

let str = "How are you doing today?";
console.log(capitalize(str));

2)

function capitalize(str){
  let wordList = str.split(" ");

  wordList.forEach(function(word){
    word = word[0].toUpperCase() + word.substring(1);
  })

  return wordList.join(' ');
};

let str = "How are you doing today?";
console.log(capitalize(str));
Nataliya
  • 47
  • 4
  • 2
    `word` is passed by value to the callback function of `forEach()`. You're not overwriting the element in the array. – Patrick Roberts Dec 26 '19 at 18:29
  • Try `wordList = wordList.map(function(word){ return word[0].toUpperCase() + word.substring(1); })`; instead. Or `wordList.forEach(function(word, index, array){ array[index] = word[0].toUpperCase() + word.substring(1); })` if you insist on using `forEach()` instead of `map()`. – Patrick Roberts Dec 26 '19 at 18:30

5 Answers5

1

You have to use .map instead of .forEach as map returns a new array with changed (mapped) values.

wordList = wordList.map((word) =>
    word[0].toUpperCase() + word.substring(1)
  )
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
1

You can use String.replace() with a regular expression (regex101):

function capitalize(str) {
  return str.replace(/\b./g, c => c.toUpperCase());
};

const str = "How are you doing today?";

const result = capitalize(str);

console.log(result);

Why doesn't assigning in the Array.forEach() work?

Since word is a string (a primitive like number or boolean), and primitives in JS are immutable (you can't change them, reassigning the variable has no effect. In addition, the values are store in the array, and you can change the array in a very ugly way (Not recommended. Don't use!), because arrays in JS are mutable (can be changed).

function capitalize(str) {
  let wordList = str.split(" ");

  wordList.forEach(function(word, i) {
    wordList[i] = word[0].toUpperCase() + word.substring(1);
  })

  return wordList.join(' ');
};

let str = "How are you doing today?";
console.log(capitalize(str));
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

You can still use your own forEach, update the code as below, Here the callback for forEach takes 2nd argument the index, and you can store the modified value inside wordList and not in word.

function capitalize(str){
    let wordList = str.split(" ");

    //console.log(wordList);

    wordList.forEach(function(word, index){
        wordList[index] = word[0].toUpperCase() + word.substring(1);
    })

    return wordList.join(' ');
  };

  let str = "How are you doing today?";
  console.log(capitalize(str));
Tinu Jos K
  • 888
  • 1
  • 8
  • 21
0

Here is the solution :) Basically, you forgot to update the initial array.

function capitalize(str){
  let wordList = str.split(" ");
  wordList.forEach(function(word, ind){
    word = word[0].toUpperCase() + word.substring(1);
    wordList[ind] = word;
  })

  return wordList.join(' ');
};

let str = "How are you doing today?";
console.log(capitalize(str));
V.Volkov
  • 731
  • 3
  • 12
-1

forEach does nothing to modify the target array, you're simply throwing away the assignments. The function you're looking for is map which will transform each value and return a new array. In this case:

function capitalize(s) {
  return s.split(' ').map(w => `${w[0].toUpperCase()}${w.substring(1)}`).join(' ')
}

console.log(capitalize('some words'))
aw04
  • 10,857
  • 10
  • 56
  • 89