I’m trying to write a function that takes a string and capitalizes the first letter in each word that is not included in the “minorWords” string. What is missing in my code that causes the return value to be “undefined”? After writing this function a few different ways I am now thinking that I am just using .forEach incorrectly. I am fairly certain that I am using the ternary operator appropriately, but I tried substituting an if statement and got the same result ( undefined ). I am also not sure why undefined is being returned twice . . .
function titleCase1(title, minorWords) {
var titleArray = title.split(" ");
var minorArray = minorWords.split(" ");
var newArray = titleArray.forEach(function(word){
(word in minorArray)? word :
word[0].toUpperCase() + word.slice(1);
})
console.log(newArray);
}
titleCase1("the wind in the willows", "the in");
// -> undefined undefined
I realize that if this works the first "the" will not be capitalized, but I will figure that out once I am no longer misusing the tools I have here . . .
There're two problems with your code:
The only thing forEach
does is execute a callback for each element in an Array and does NOT return anything, therefore newArray
will always be undefined
. For reference check how forEach
works here.
If you want to create a new Array with values like how you're trying to do with newArray
. You need to use map
, but you actually require to return a value from the callback. For reference check how map
works here.
You can't use the in
operator to see if a word is present in your Array. The in
operator only checks if a specified property is present in a specified Object. Therefore it will always return false
when used for checking an element inside of an Array. Because an Array in javascript is actually an Object under the hood!
var a = [ 'a', 'b', 'c' ];
is actually
var a = { 0: 'a', 1: 'b', 2: 'c' };
Therefore 'a' in [ 'a', 'b', 'c' ]
will always return false
and for example 0 in [ 'a', 'b', 'c' ]
will return true
.
Because of this caveat you should change your approach and for example use indexOf
. For reference check how indexOf
works here.
With this in mind you could modify your code to the following to get the desired behaviour:
function titleCase1(title, minorWords) {
var titleArray = title.split(' ');
var minorArray = minorWords.split(' ');
var newArray = titleArray.map(function (word) {
// indexOf returns the elements index on match or -1.
var match = minorArray.indexOf(word) != -1;
// If there's a match, return the (lowercased) word, otherwise uppercase it.
return match ? word : (word[0].toUpperCase() + word.slice(1));
});
console.log(newArray);
}
titleCase1("the wind in the willows", "the in"); // [ 'the', 'Wind', 'in', 'the', 'Willows' ]