1. Template literal이란?

string literal
문자 그대로의.
Template literal
템플릿 그대로의.

1-1. Template literal의 장점

  • backtick (`)
    var a = 'abc';
    var a = "abc";
    var a = `abc`;
    

    이 세개는 모두 같은 값.

  • multi-line
var a = 'abc\n' +
'def';
console.log(a)
// "abc
// def"

var b = `a
bb
ccc`;
console.log(b)
// "a
// bb
// ccc"
  • string interpolation(문자열 안에 보간, 끼워넣기)
const a = 10
const b = 20
const strBefore = a + ' + ' + b + ' = ' + (a + b);

const str = `${a} + ${b} + = ${a + b}`
console.log(str)

이렇게 ${ }로 묶은 것 안에는 이나 , 함수의 호출을 넣을 수 있음.
은 값이 없기 때문에 넣지 못함!

1-2. Template literal 상세

  • 1) multi-line의 경우 들여쓰기에 주의해야함.
var a = 'abc\n' +
            'def';
console.log(a)
// "abc
// def"

var b = `a
  bb
    ccc`;
console.log(b)
// "a
//   bb
//    ccc"

들여쓰기하면 그대로 출력된다

함수에서 문제가 될 수 있음.

const f = function () {
  const a = `abc
    def
    ghij`;
console.log(a)
}
f()
// 결과
//  abc
//     def
//     ghij

함수를 실행하면 들여쓰기가 그대로 출력된다.

const f = function () {
  const a = `abc\n`+
    `def`+
    `ghij`;
console.log(a)
}
f()
// 결과
//  abc
//  def
//  ghij

기존처럼 사용하면 들여쓰기 문제 해결.
여전희 백틱 안에서는 보간을 사용할 수 있음.

  • 2) 결국 문자열이라 자동으로 toString 처리된다
console.log(`${[0,1,2]})`) // 0,1,2
console.log(`$)`) // [object object]
console.log(`${function(){return 1}})`) // function()
console.log(`${(() => 1)()}` + 1 ) // 11
  • 배열의 toString
  • 객체의 toString
  • 함수의 toString
  • 즉시실행함수의 toString

즉시실행함수가 어떻게 저렇게 나오는가?

`${(function(){ return 1; })()})` // '1'
+ 1

함수를 괄호로 감싸서 즉시실행함수 실행.
1을 반환. 백틱으로 감쌌기 때문에 문자열.

  • 숫자 1을 더함
    = 문자열 1 + 숫자 1 => 더해져서 11!

  • 3) 중첩된 backtick 처리

console.log(`     Foo ${` Bar `}     `)
console.log(`    Foo ${`   Bar ${` Bar `}   `}   `)
  • 4) 앞 뒤를 트림처리 할 수 있다.
function a () {
  return `
<div>
    <h1>Lorem ipsum.</h1>
</div>
  `.trim()
}
// 백틱과 div사이에 들어갈 공백만 trim처리하면 됨.
console.log(a())
console.log(a().replace(/\n/g, ''))

Template literal이 나오게 된 계기?

reduce를 배운 뒤에 다시 듣기

const linesToHTML = function (characters) {
  return characters.reduce(function (charactersResult, character) {
    let {name, lines} = character
    return `${charactersResult || ''}
<article>
  <h1>${name}</h1>
  <ul>
    ${lines.reduce(function (linesResult, line) {
      return `${linesResult || ''}
    <li>${line}</li>
      `.trim()}, 0)}
  </ul>
</article>
  `.trim()}, 0)
}
const characters = [{
  name: 'Aria Stark',
  lines: ['A girl has no name.']
}, {
  name: 'John Snow',
  lines: [
    'You know nothing, John Snow.',
    'Winter is coming.'
  ]
}]
document.body.innerHTML = linesToHTML(characters)

2. forEach, map, reduce

2-1. forEach

for문을 편하게 쓰기 위한 방법!

Array.prototype.forEach(callback[, thisArg])

forEach는 인자를 두개 받는다.
콜백함수라는 인자와, 생략이 가능한 thisArg

  • callback

    function (currentValue, [, index[, originalArray]])

    • currentValue : 콜백함수를 실행하는 배열의 현재값이 들어옴(필수)
    • index : 현재 인덱스가 들어옴(생략가능)
    • originalArray: 원본 배열(생략가능)
  • thisArg
    • this에 할당할 대상. 생략시 global객체
const a = [ 1, 2, 3 ]
a.forEach(function (v, i, arr) {
    console.log(v, i, arr, this)
}, [ 10, 11, 12 ])


결과

근데 여기서 this를 뭐하러 넣어?

const a = [ 1, 2, 3 ]
a.forEach(function (v, i, arr) {
    console.log(this.[i])
}, [ 10, 11, 12 ]) // 10, 11, 12

뭐 이렇게 a를 가지고 순회를 돌면서,
다른 this의 i를 써야할 수도 있으니까~

2-2. map

Array.prototype.map(callback[, thisArg])

  • callback

    function (currentValue[, index[, originalArray]])

    • currentValue: 현재값
    • index: 현재 인덱스
    • originalArray: 원본 배열
  • thisArg: this에 할당할 대상. 생략시 global객체
const a = [ 1, 2, 3 ]
const b = a.map(function (v, i, arr) {
    console.log(v, i, arr, this)
    return this[0] + v
}, [ 10 ])


결과

2-3. reduce

es5에서 등장.

Array.prototype.reduce(callback[, initialValue])

  • initialValue: 초기값. 생략시 첫번째 인자가 자동 지정되며,
    이 경우 currentValue는 두번째 인자부터 배정된다.
  • callback

    function (accumulator, currentValue[, currentIndex[, originalArray]])

    • accumulator: 누적된 계산값
    • currentValue: 현재값
    • currentIndex: 현재 인덱스
    • originalArray: 원본 배열

2-3-1. initial value 유무의 차이

  • 1) initial value 있을 경우
    const arr = [ 1, 2, 3 ]
    const res = arr.reduce(function (p, c, i, arr) {
    console.log(p, c, i, arr)
    return p + c
    }, 10)
    


예제

const arr = [ 1, 2, 3, 4 ]
const str = arr.reduce(function (res, item, index, array) {
  return res + item
}, '') // initial value 있음
console.log(str)
step res item index array
1 '' 1 0 [1,2,3,4]
2 ‘1’ 2 1 [1,2,3,4]
3 ‘12’ 3 2 [1,2,3,4]
4 ‘123’ 4 3 [1,2,3,4]
result ‘1234’      
  • 2) initial value 없을 경우
const arr = [ 1, 2, 3 ]
const res = arr.reduce(function (p, c, i, arr) {
  console.log(p, c, i, arr)
  return p + c
})
console.log('res', res)


예제

const arr = [ 1, 2, 3, 4 ]
const str = arr.reduce(function (res, item, index, array) {
  return res + item
}) // initial value 없음
console.log(str)
step res item index array
1 'a' ‘b’ 1 [‘a’,’b’,’c’,’d’]
2 ‘ab’ ‘c’ 2 [‘a’,’b’,’c’,’d’]
3 ‘abc’ ‘d’ 3 [‘a’,’b’,’c’,’d’]
result ‘abcd’      

2-3-2. reduce의 활용

  • 1) 문자열을 만들 수 있음
const arr = [ 'a', 'b', 'c', 'd' ]
const str = arr.reduce(function (res, item, index, array) {
  return res + item
})
console.log(str)
// 결과 : abcd
  • 2) 객체를 만들 수 있음
const arr = [ 'a', 'b', 'c', 'd' ]
const str = arr.reduce(function (res, item, index, array) {
  res[item] = item;
  return res;
},{}) //initial value 없음
console.log(str)

// {a:'a', b:'b', c:'c', d:'d'}


근데 이해안됨….

예제

𝑸. 1 ~ 10까지 더하라.

  • for로 하면….
const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let res = 0;
for(let b = 0; b < a.length; b++) {
  res += a[b];
}

// 결과 55

세상 오래걸림

  • reduce로 하면…..
const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

const res = a.reduce(a,c => a + c);


2-4. 이 모든 것들의 공통점!

배열의 모든 메소드의 받는 인자는, 중요한 순서로 나열되어있다.

  • forEach
    • currentValue 필수, index 필수X
  • map
    • currentValue 필수, index 필수X
  • reduce
    • accumulator 필수, currentValue 필수, index 필수X

jQuery의 each메소드는 index, item순서이니 헷갈릴 수 있음

2-4. 이 모든 것들의 차이점!

  • forEach
    • for문 돌리는 것과 같은 개념
  • map
    • for문을 돌려서 새로운 배열을 만드는 목적
    • 그래서 반드시 return 필요!
  • reduce
    • for문을 돌려서 최종적으로 다른 무언가를 만드는 목적
    • 그래서 반드시 return 필요!

3. tag function

const tag = function (strs, arg1, arg2) {
  return {strs: strs, args: [arg1, arg2]}
}
const res = tag `순서가 ${1}이렇게 ${2}`
console.log(res)
const tags = function (strings, ...expressions) {
  console.log(strings, expressions)
}
const a = 'iu', b = 'Friday'
const str = tags `Hello, ${a}! Today is ${b}!!`
// ["Hello, ", "! Today is ", "!!"]
// ["iu", "Friday"]
  • strings와 expression을 조합한 예제
const setDecimalSeperators = function (strs, ...args) {
  return args.reduce(function (p, c, i) {
    return p + strs[i] + (c + '').replace(/\d{1,3}(?=(\d{3})+(?!\d))/g, '$&,')
  }, '') + strs[strs.length - 1]
}
const res = setDecimalSeperators `이 사과는 하나에 ${2000}원이고, 총 ${1234567}개를 구입하시면 총 ${2000 * 1234567}원 이에요.`
console.log(res)