대가는 결과를 만든다

[스터디] Javascript ES6 feature 몇 가지 정리 본문

개발/Javascript

[스터디] Javascript ES6 feature 몇 가지 정리

yunzema 2019. 2. 1. 10:37
반응형

vue, webpack을 이용하여 개발을 하면서 ES6 문법 공부가 불가피해짐..

기본적인 module 문법과 ES6의 문법 차이점을 비교하며 정리해본다!



1. module 문법


1) named exports


: 듈 중 일부 필요로 하는 경우가 있을 때 사용 (하나의 함수 혹은 하나의 클래스만 사용하고 싶은 경우)


    //------ lib.js ------
    export const sqrt = Math.sqrt;
    export function square(x) {
        return x * x;
    }
    export function diag(x, y) {
        return sqrt(square(x) + square(y));
    }


가능한 사용 형식


a) - 일부만 import하여 사용

//------ main.js ------ import { square, diag } from 'lib';

console.log(square(11)); // 121 console.log(diag(4, 3)); // 5

b) - attribute로 export한 변수 접근

    //------ main.js ------
    import * as lib from 'lib';
    console.log(lib.square(11)); // 121
    console.log(lib.diag(4, 3)); // 5


2) default exports


: 하나의 module이 통째로 export (프론트엔드에서 주로 사용)


a) 함수인 경우

    //------ myFunc.js ------
    export default function () { ... };
    //------ main1.js ------
    import myFunc from 'myFunc';
    myFunc();

b) 클래스인 경우

//------ MyClass.js ------
    export default class { ... };
    //------ main2.js ------
    import MyClass from 'MyClass';
    let inst = new MyClass();

c) es6에서는 "_" 는 default exports를 의미, "each"나 "foreach"는 named exports를 의미

* defaul;t exports와 named exports 동시에 얻는 방법도 가능


//------ underscore.js ------ export default function (obj) { ... }; export function each(obj, iterator, context) { ... }

    //------ main.js ------
    import _, { each } from 'underscore';
    ...


2. Default Parameter


1) 기존 방식

var link = function (height, color, url) {
    var height = height || 50
    var color = color || 'red'
    var url = url || 'http://azat.co'
    ...
}

2) ES6 사용가능한 방식

var link = function(height = 50, color = 'red', url = 'http://azat.co') {
  ...
}

* 차이점 주의인자값으로 0 또는 false가 입력될 때 두 예시의 결과는 다르다. ES5에서는 || 처리 시 0 또는 false 값이 입력 되어도 거짓이 되므로 기본값으로 대체된다. 하지만 ES6의 기본 매개 변수를 사용하면 undefined 를 제외한 입력된 모든 값(0, false, null 등)을 인정한다.



3. Template Literals, Multi-line Strings


1) 문자열 처리 기존 방식

var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id

2) ES6 ` ` 안에 ${변수명}을 이용하여 처리 가능

var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`

3) 멀티라인 문자열 표현도 ` `을 이용하여 표현 가능

var roadPoem = `Then took the other, as just as fair, And having perhaps the better claim Because it was grassy and wanted wear, Though as for that the passing there Had worn them really about the same,`

*주의 : ' '이 아닌 ` `임을 주의해야 한다.. 예제를 보고 오타인 줄 알고 삽질 했던 경험이...



4. 비구조화 할당


1) 기존방식 : 구조화된 데이터를 변수로 받기 위해 아래와 같은 처리해야 했음.

// browser
var data = $('body').data(), // data has properties house and mouse
  house = data.house,
  mouse = data.mouse

// Node.js
var jsonMiddleware = require('body-parser').json

var body = req.body, // body has username and password
  username = body.username,
  password = body.password

2) ES6 비구조화 할당을 사용해 처리 가능

var {house, mouse} = $('body').data() // we'll get house and mouse variables

var {jsonMiddleware} = require('body-parser')

var {username, password} = req.body

*주의 : var로 할당하려는 변수명과 구조화된 데이터의 property명이 같아야 한다.


3) 구조화된 데이터가 아닌 배열인 경우 {} 대신 []를 사용해 유사하게 사용 가능하다

var [col1, col2]  = $('.column'),
  [line1, line2, line3, , line5] = file.split('\n')


5. Enhanced Object Literals


1) 기존 객체 리터럴 생성

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}

var accountServiceES5 = {
  port: serviceBase.port,
  url: serviceBase.url,
  getAccounts: getAccounts,
  toString: function() {
    return JSON.stringify(this.valueOf())
  },
  getUrl: function() {return "http://" + this.url + ':' + this.port},
  valueOf_1_2_3: getAccounts()
}

2) ES6 

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}
var accountService = {
    __proto__: serviceBase,
    getAccounts,
    toString() {
     return JSON.stringify((super.valueOf()))
    },
    getUrl() {return "http://" + this.url + ':' + this.port},
    [ 'valueOf_' + getAccounts().join('_') ]: getAccounts()
};
  • __proto__ 속성을 사용해서 바로 프로토타입을 설정할 수 있다.
  • getAccounts: getAccounts, 대신 getAccounts, 를 사용할 수 있다 (변수명으로 속성 이름을 지정).
  • [ 'valueOf_' + getAccounts().join('_') ] 와 같이 동적으로 속성 이름을 정의할 수 있다.


6. Arrow Functions


화살표 함수는 익명 함수이며, this의 값을 현매 문맥에 바인딩 가능


1) 기존 ES5에서의 this 사용 위한 처리

var _this = this
$('.btn').click(function(event){
  _this.sendData()
})

1-1) 화살표 함수로 대체한 예시

$('.btn').click((event) => {
  this.sendData()
})

2) ES5에서의 call 사용하여 context를 함수에 전달

var logUpperCase = function() {
  var _this = this

  this.string = this.string.toUpperCase()
  return function () {
    return console.log(_this.string)
  }
}
logUpperCase.call({ string: 'es6 rocks' })()

2-1) ES6 화살표 함수 사용

var logUpperCase = function() {
  this.string = this.string.toUpperCase()
  return () => console.log(this.string)
}
logUpperCase.call({ string: 'es6 rocks' })()

3) 기타 예시

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(function (value) {
  return "ID is " + value // explicit return
});
var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(value => `ID is ${value}`) // implicit return

*여러 개의 인자를 사용하는 경우는 변수 목록을 () 로 감싸줘야 한다.

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map((value, index, list) => `ID of ${index} element is ${value} `) // implicit return

*본문을 괄호로 감싸 객체 표현식을 반환할 수 있으며 ... 을 이용해 가변 파라미터를 사용할 수도 있다.

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map((value, index, ...abc) => ({v:value, i:index, a:abc}))


7. Promise


비동기 실행 관련


1) ES5 setTimeout을 이용 예시

setTimeout(function(){
  console.log('Yay!')
}, 1000)

2) ES6 Promise

var wait1000 =  new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000)
}).then(function() {
  console.log('Yay!')
})

2-1) 화살표 함수 이용 ES6 Promise

var wait1000 =  new Promise((resolve, reject)=> {
  setTimeout(resolve, 1000)
}).then(()=> {
  console.log('Yay!')
})

3) 중첩된 setTimeout의 예시로 보는 Promise의 이점


3-1) 기존 방식

setTimeout(function(){
  console.log('Yay!')
  setTimeout(function(){
    console.log('Wheeyee!')
  }, 1000)
}, 1000)

3-2) ES6 Promise

var wait1000 =  ()=> new Promise((resolve, reject)=> {setTimeout(resolve, 1000)})

wait1000()
    .then(function() {
        console.log('Yay!')
        return wait1000()
    })
    .then(function() {
        console.log('Wheeyee!')
    });


8. Block-Scoped Constructs Let and Const


let과 const는 { }로 정의된 블록으로 유호범위를 지정하는 새로운 var 이다. let은 변수 const는 상수를 선언


1)  var는 전역 또는 함수 내부로 유효 범위를 갖기 때문에 예시에 사용된 함수 내부의 "{}" 들은 아무런 역할을 못함.

function calculateTotalAmount (vip) { var amount = 0 if (vip) { var amount = 1 } { // more crazy blocks! var amount = 100 { var amount = 1000 } } return amount } console.log(calculateTotalAmount(true))            //출력 1000

2)  let 사용 예시 : let으로 선언한 변수는 {}내부에서만 유효하므로 amount의 100, 1000 대입은 {} 내부에서만 유효한 값이다.

function calculateTotalAmount (vip) { var amount = 0 // probably should also be let, but you can mix var and let if (vip) { let amount = 1 // first amount is still 0 } { // more crazy blocks! let amount = 100 // first amount is still 0 { let amount = 1000 // first amount is still 0 } } return amount } console.log(calculateTotalAmount(true))            //출력 0

3) const 사용 예시 : const는 상수를 선언하는 것으로 여러번 선언 불가능하지만 let과 같이 {} 블록 내부에서만 유효하므로 아래 예시는 오류 발생하지 X

function calculateTotalAmount (vip) {
  const amount = 0
  if (vip) {
    const amount = 1
  }
  { // more crazy blocks!
    const amount = 100
    {
      const amount = 1000
      }
  }
  return amount
}
console.log(calculateTotalAmount(true))            //출력 0


9. Class


prototype 기반 상속보다 명확하게 정의 가능 get, set, static 키워드를 사용해 메서드 정의 가능


1) constructor사용, property의 경우 메소드와 달리 생성자에서 값을 할당해야 한다.

class baseModel {
  constructor(options = {}, data = []) { // class constructor
        this.name = 'Base'
    this.url = 'http://azat.co/api'
        this.data = data
    this.options = options
    }

    getName() { // class method
        console.log(`Class name: ${this.name}`)
    }
}

2) class NAME extends PARENT_NAME 형식으로 상속이 가능하다. 상속시 부모 생성자를 호출하기 위해 super() 를 사용할 수 있다. 생성자가 아닌 메소드에서는 super 키워드를 사용해서 부모 메소드에 접근한다.

class AccountModel extends baseModel {
    constructor(options, data) {
      super({private: true}, ['32113123123', '524214691']) //call the parent method with super
      this.name = 'Account Model'
      this.url +='/accounts/'
    }

    get accountsData() { //calculated attribute getter
      // ... make XHR
      return this.data
    }
}

3) 사용

let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)
Class name: Account Model
Data is %s 32113123123,524214691


feature 참고 : https://blog.asamaru.net/2017/08/14/top-10-es6-features/

좀 더 디테일한 번역 참고 : https://jsdev.kr/t/es6/2944

참고 : https://enyobook.wordpress.com/2016/08/17/export-default%EC%97%90-%EB%8C%80%ED%95%B4/

'개발 > Javascript' 카테고리의 다른 글

[스터디] javscript의 상속 Traditional vs ES6  (0) 2019.09.24
web worker  (0) 2019.07.25
javascript의 prototype이란?  (0) 2018.12.20
[이슈] jQuery click 이벤트 중복으로 인한 문제  (4) 2018.12.14
Navigator  (0) 2018.12.04
Comments