ES6 - Create Strings using Template Literals

Tell us what’s happening:
Could someone help me understand where I’m going wrong here?

Your code so far

const result = {
  success: ["max-length", "no-amd", "prefer-arrow-functions"],
  failure: ["no-var", "var-on-top", "linebreak"],
  skipped: ["no-extra-semi", "no-dup-keys"]
};
function makeList(arr) {
  // Only change code below this line
  const failureItems = [
    `<li class = "text-warning">${result.failure[0]}</li>',
  '<li class = "text-warning">${result.failure[1]}</li>',
  '<li class = "text-warning">${result.failure[2]}</li>`;
  ];
  return arr.push(failureItems); 
  // Only change code above this line

  return failureItems;
}

const failuresList = makeList(result.failure);

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36

Challenge: ES6 - Create Strings using Template Literals

Link to the challenge:

  1. You have a syntax error. Read the error message and find the ; that shouldn’t be there (inside the array).

  2. You are asked to use an iterator method.

Use an iterator method (any kind of loop) to get the desired output (shown below).

  1. .push() returns the new length of the array after the push operation. That is not what you are supposed to return.

  2. Make sure the strings you are creating do not have anything unexpected, like spaces where you do not need there to be spaces (like the class names part).

If I used a for loop, how will the code know to access all 3 outputs for the failure property?

Because the loop gives you access to the elements inside the array.

const names = ['John', 'Paul', 'George', 'Ringo'];

function addNames(names) {
  return names.map((name) => (
    `<h2 class="name">${name}</h2>`
  ));
}

console.log(addNames(names));
// ['<h2 class="name">John</h2>', '<h2 class="name">Paul</h2>', '<h2 class="name">George</h2>', '<h2 class="name">Ringo</h2>']

How do you think through what to add to the return to get what you want? I’ve never seen the .map operator? Also how do I share my updated code to see if I’m tracking with you?

Push each template string to an array with each of the elements embedded as variables. Then return the array.

You do not need to the .map() array method and I’m trying not to post code too close to the solution.

Here is the same function using a for...of (normal for loop works as well).

function addNames(names) {
  const nameList = [];
  for (const name of names) {
    nameList.push(`<h2 class="name">${name}</h2>`);
  }
  return nameList;
}

You can use the “preformatted text” tool in the editor (</>) to add backticks around your code.

Okay now what am I doing wrong?

const result = {
  success: ["max-length", "no-amd", "prefer-arrow-functions"],
  failure: ["no-var", "var-on-top", "linebreak"],
  skipped: ["no-extra-semi", "no-dup-keys"]
};
function makeList(arr) {
  // Only change code below this line

  const failureItems = []
     for (const failure in result) {
       failureItems.push(`'<li class="text-warning">${result.failure}</li>'`)
     };
 
  // Only change code above this line

  return failureItems;
}

const failuresList = makeList(result.failure);

Here’s a hint, these are the same:

const string1 = `this is a string`;
const string2 = 'this is a string';
console.assert(string1 === string2);
  1. You should be looping the arr parameter. The result.failure array is passed to the function parameter.

  2. The variable in the for…of loop is each of the elements and is what you should use for the template string.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

for (const number of numbers) {
  console.log(number);
}

Just getting more and more confused, can you use dumb noob language to help me understand what I’m doing and how it needs to change?

const result = {
  success: ["max-length", "no-amd", "prefer-arrow-functions"],
  failure: ["no-var", "var-on-top", "linebreak"],
  skipped: ["no-extra-semi", "no-dup-keys"]
};
function makeList(arr) {
  // Only change code below this line

  const failureItems = []
     for (const makeList of arr) {
       failureItems.push(`<li class="text-warning">${result.failure[0]}</li>,<li class="text-warning">${result.failure [1]}</li>,
  <li class="text-warning">${result.failure[2]}</li>`)
     };
 return arr
  // Only change code above this line

  return failureItems;
}

const failuresList = makeList(result.failure);

The for…in loop in JS is used only to loop through properties of Objects – objects being a specific datatype that Arrays are not.

// Object: 
const object = { a: 1, b: 2, c: 3 };
// Array:
const array = [0, 1, 2];

When i’m debugging things like this, the problem is usually that I’m not clear on the actual value or type of the variables. If you have a bug with something like this:

const addNumbers = function(a, b) {
  const sum = a + b;
  return sum;
}

Then there is almost certainly a problem with my assumptions about what the parameters of that function contain. This is a common complaint of dynamically typed languages, and why typed languages can help – if you try to pass a string to a variable that was initialized as an integer, javascript says OK, other languages will warn you that you’re probably misunderstanding something.

So back to your code. We know we can’t use a for…in loop on an array. There are a few things we can use, but to keep things simple for now we’ll use a standard for loop. That type of loop just gives us an integer that increases by 1 each time around.

for (let i = 0; i < arr.length; i++) {
  // i is commonly used for loop variables by convention. 
  // I think it stands for incrementer
}

There is one thing I didn’t mention – we need to tell the loop when to stop. That’s the middle condition in the for loop parentheses: i < arr.length. (I read this code in my head as ‘for let i equal zero, while i is less than array dot length, increment i’) arr.length is a property of all array data types in JS, and gives us an integer value for the number of items in the array. Since arrays are 0-indexed in programming, that means that if we have [0, 1, 2] the length property will be 3. This is a common source of bugs that you should be aware of, and the reason we use < instead of <= here. It even has its own wikipedia page

Ok so now we have a for loop that’s giving us the numbers 0, 1, 2... n-1 where n is the length of our input array.

Your use of the push method is correct here, and that’s not a problem. The problem arises from what you’re passing into the push method: result.failure[0]. This issue is complex and has to do with scope. I recommend you do some reading until you understand scope better, as it will really help you understand programming best practices and programming in general on a higher level. Simply put, the result variable is not in the scope of the makeList() function. This means that if you reference the result variable, which lies in the global scope, it will have unintended side-effects. A good rule of thumb with functions is to lean towards ‘pure functions’ a.k.a. functions that only operate on their explicit parameters. This makes the code more maintable in the future (note that this isn’t always possible).

Now we do have access to the data inside the result variable, because it was passed as a parameter when the function was called at the end of the file: const failuresList = makelist(result.failure);

This means that the arr parameter will contain the array in the failure property of the result object.

Now we just have to loop through the arr parameter to access each item indexed in the array:

for (let i = 0; i < arr.length; i++) {
  failureItems.push(`<li class="text-warning">${arr[i]}</li>`)
};

Hopefully this helps. Let me know if you have any questions.

The fact that you keep hardcoding the values in your loop suggests to me you have not fully understood the point of a loop. The for...of loop gives you access to each element. A normal for loop gives you an index you can use to access each element.

You keep accessing the top-level result.failure array. Do not do that. It is passed into the function when the function is called and put into the arr parameter. You then loop the arr (which is the same as result.failure) and inside that loop, you get access to each element of that array. You then use each of those elements in the template string. One for each iteration. For each loop iteration, you should only push a single template string.

You have two returns in your function. Only the first return is going to do something and it is returning the wrong array. You should be returning failureItems not arr.


@mdm5995 The function very much has access to the outer scope. Also, I have blurred the last piece of code as that is just too close to solution code.

Finally! Thanks for being patient guys. I definitely don’t remember learning anything besides for and while loops so the of/in stuff I was reading was really confusing and I was using my limited knowledge of js to try to make it make sense

Good the hear you got it.


Again, both .map() and for...of is not needed. The reason I used them is they are cleaner and it made it harder for you to just copy/paste the examples.

I will say, at one point, this challenge came after the functional programming section which teaches .map() and most people did in fact solve this challenge using a map (pretty sure). If you know .map() that is how I would suggest doing it.

The standard for loop is (in my opinion) to be avoided unless you need it. But if that is all you have been taught at this point, well then that is the only tool you have. It can do it all and there is no harm in using it until you have learned about the alternatives. But once you have, there are often better options.

Yeah I have been going straight down the basic javascript and algorithms modules and have not learned .map()

Totally as intended. Following the curriculum order is advised.

Anyway, .map() is a very neat method. One you will be using a lot in the future.

Good point, I updated my response to make my intent clearer.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.