126

I've an array with a list of elements and I'm trying to append this list to an HTML element using template strings:

var description = [
  'HTML & CSS',
  'Javascript object-oriented programming',
  'Progressive Web apps (PWAs)',
  'Website Performance Optimization',
  'Webpack and Gulp workflows',
  'Fullstack React.js',
  'Web Components',
  'Responsive web design',
  'Sketch design',
  'GraphQL and Relay'
]

$('body').append(
  `
  <div class="description">
    <ul>
      ${description.map(
        function(work) {
          return `<li>${work}</li>`
        }
      )}</ul>
  </div>
  `
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

As a result I get an unexpected comma between each list element. (You can see this when you run the code snippet above.)

How can I avoid this?

Ivar
  • 6,138
  • 12
  • 49
  • 61
Lc0rE
  • 2,236
  • 8
  • 26
  • 34
  • The `map()` function is ok. The problem should come from somewhere else – Weedoze Aug 22 '17 at 08:06
  • Looks like you are using some kind of templating language here; which one? – CBroe Aug 22 '17 at 08:07
  • I'm using plain JS (ES2015) here (just a jQuery selection to the body and to append the element). Added a snippet to the description. – Lc0rE Aug 22 '17 at 08:10
  • @CBroe: Those are ES2015+ [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). – T.J. Crowder Aug 22 '17 at 08:11

4 Answers4

282

Explanation

template literals use the toString() method which by default joins the returned array by map with a ,.
To avoid this "problem" you can use join('')

Code

var description = [
  'HTML & CSS',
  'Javascript object-oriented programming',
  'Progressive Web apps (PWAs)',
  'Website Performance Optimization',
  'Webpack and Gulp workflows',
  'Fullstack React.js',
  'Web Components',
  'Responsive web design',
  'Sketch design',
  'GraphQL and Relay'
]

$('body').append(
  `
  <div class="description">
    <ul>
     ${
        description.map(function(work) {
          return `<li>${work}</li>`
        }).join('')
      }
    </ul>
  </div>
  `
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Brandon Benefield
  • 1,504
  • 1
  • 21
  • 36
Roman
  • 4,922
  • 3
  • 22
  • 31
39

.map() returns an array. You probably want to return a string containing the array elements concatenated together. You can do that with .join(''):

var description = [
  'HTML & CSS',
  'Javascript object-oriented programming',
  'Progressive Web apps (PWAs)',
  'Website Performance Optimization',
  'Webpack and Gulp workflows',
  'Fullstack React.js',
  'Web Components',
  'Responsive web design',
  'Sketch design',
  'GraphQL and Relay'
]

$('body').append(
  `
  <div class="description">
    <ul>
      ${description.map(
        function(work) {
          return `<li>${work}</li>`
        }
      ).join('') /* added .join('') here */}</ul>
  </div>
  `
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Michael Geary
  • 28,450
  • 9
  • 65
  • 75
  • how does map returns array? we are already telling it to return a template literal right? – Rohan Devaki Apr 17 '21 at 04:28
  • 1
    Can you clarify what you're asking? `.map` always returns an array. We can't tell it to return a template literal and aren't doing so here. – Michael Geary Apr 17 '21 at 04:52
  • ``` ${description.map( function(work) { return `
  • ${work}
  • ` } ``` here we are returning the template literlal `
  • ${work}
  • ` right? so how is it again converting into array? – Rohan Devaki Apr 17 '21 at 15:46
  • You're looking at the `return` from the _callback_, not from `array.map` itself. The `array.map` method creates a new array, then iterates through the existing array, calls your callback function on each element, and pushes onto the new array whatever value your callback returns. Finally, it returns the new array. Here is a simple example you can try in your browser's dev tools: `let a = [5,10,15]; let b = a.map( function(x) { return -x; }); console.log(a); console.log(b);` As you can see, the `return` statement in the callback returns a number, but `map` collects all those into a new array. – Michael Geary Apr 18 '21 at 03:02