Extra substitution when rendering a tagged template literal

59 Views Asked by At

I just started to use template literals and tagged template literals. But I'm running into a problem when trying to render a template literal because it renders an extra substitution that I can wonder where it comes from.

This is what I have tried:

My data

var data = {
    login: "john_12",
    name: "John",
    bio: "developer",
    email: "[email protected]"
}

My tag function

function replaceNullData(strings, ...parts) { 
     var checkedMarkup = ""; 
     strings.forEach((string, index) => { 
         if (!parts[index]){ 
             parts[index] = "data no available"; 
         } 
         checkedMarkup += string + parts[index]; 
     }); 

     return checkedMarkup; 
 }

My template literal

var summaryMarkup = replaceNullData`
         <div>
             <p>Username: ${data.login}</p>
         </div>
         <div>
             <p>Name: ${data.name}</p>
         </div>
         <div>
             <p>Bio: ${data.bio}/<p>
         </div>
         <div>
             <p>Email: ${data.email}</p>
         </div>
     `; 

Now, if I do console.log(summaryMarkup);, I obtain this:

     <div> 
         <p>Username: john_12</p> 
     </div> 
     <div> 
         <p>Name: John</p> 
     </div> 
     <div> 
         <p>Bio: developer/<p> 
     </div> 
     <div> 
         <p>Email: [email protected]</p> 
     </div> 
 data no available <------- THIS IS WHAT SHOULDN'T APPEAR

There is an extra "data no available" at the end. It's like the tag function received 6 parts (substitution or expressions) instead of 5.

What am I missing here?

1

There are 1 best solutions below

0
On BEST ANSWER

Your parts.length is the length you expected, but notice you're iterating strings, not parts. strings.length === parts.length + 1, so you're accessing parts out-of-bounds. Iterate parts instead and append the last string outside the iteration:

function replaceNullData(strings, ...parts) { 
    var checkedMarkup = ""; 
    parts.forEach((part, index) => {
        if (part == null) { // because false, 0, NaN, and '' should be "available"
            part = "data not available";
        }

        checkedMarkup += strings[index] + part;
    });

    return checkedMarkup + strings[strings.length - 1]; // manually append last string
}