ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] ES6(ES2015)
    Front-End(Web)/Javascript 2021. 4. 9. 01:12
    반응형

    🧐 서론

    드디어, 내가 이전부터 포스팅하고 싶었던 Javascript의 ES6 문법이다!

    나는 2020년에 Javascript를 처음 공부했고, 오히려 ES6 문법을 당연하다는 듯이 사용하게 된 뉴비 중 한명이다. 😚😚😚

     

    최근 면접 준비를 하면서, 특히 이전 문법과 비교하는 강의들을 보면 기능과 편의성 측면에서 많은 개선을 지원해준 ES6 버전이다.

    이를 전체적으로 훑어보고 정리해봐야겠다고 생각했으며, 동시에 감사함도 느끼는 시간이 될 것 같다!


    📒 ECMAScript (선행 개념들)

    Javascript의 ES6는 일종의 버전이다. 2015년 버전이며, 마치 아이언맨에서 MK6(마크6) 와 같이 생각하면 되겠다.

    그렇다면 ES의 뜻은 무엇인지, 버전6이 같는 의미는 무엇인지 알기 위해선 우선 선행되는 개념들을 알면 좋다!

     

    - Ecam International

    정보통신에 대한 표준을 제정하는 국제 비영리 표준화 기구. 정보통신 기술 표준들을 제정하는 단체이다. (제작은 하지 않는다.)

    본래는 ECMA(European Computer Manufactureres Association) 이었으나, 국제적으로 확장되면서 International이 첨언된 것이다.

    문자 그대로, Ecma는 1961년 유럽에서 컴퓨터 시스템을 표준화하기 위해 세워졌다. (본부는 스위스 제네바 위치!)

     

    - ECMA-262

    Ecma International 로 제정된 기술규격의 일종. 범용 목적의 스크립트 언어에 대한 명세를 담고 있다.

     

    넷스케이프가 1996년 Javascript를 만들면서 표준화를 위해 기술규격을 Ecma International에 제출했고,

    이 규격에 대한 작업이 ECMA-262 라는 이름으로 1996년 11월에 시작된 것이다.

     

    - Script Language(스크립트 언어)

    스크립트 언어는 독립된 시스템에서 작동하도록 특별히 설계된 프로그래밍 언어로 정의된다.

    응용 프로그램과는 독립적으로, 사용자가 직접 응용 프로그램을 의도적으로 동작시키는데 활용되는 언어인 것이다.

     

    기본적인 프로그래밍 언어는 컴퓨터 시스템을 작동시키는 소프트웨어를 설계하기 위한 언어이다.

    스크립트 언어는 그러한 소프트웨어(어플리케이션)를 제어하기 위한 용도의 언어인 것이다.

    인터프리터 형식의 언어로 수정이 빈번한 곳에 사용된다.

     

    * Script Language(스크립트 언어) vs Compile Language(컴파일 언어)

     

    1) 스크립트 언어

    • 소스코드를 컴파일하지 않고 인터프리터로 소스 코드를 한줄씩 읽어 바로 실행하는 언어
    • 바로 실행하지만, 소스 코드를 일일히 읽기 때문에 프로그램의 실행시간은 느리다.
    • 예시 : Javascript, PHP, Ruby, Python 등

    2) 컴파일 언어

    • 소스코드를 컴파일한 후, 기계어 상태에서 CPU/메모리를 통해 읽어 실행하는 언어
    • 컴파일을 하기 때문에 규모가 큰 프로그램은 컴파일 시간이 소요되지만, 이후 실행속도는 빠르다.
    • 예시 : C++, Java 등

     

    - ECMAScript

    ECMA-262 규격에 의해 정의된 "범용 스크립트 언어". 하나의 사양이자, 스크립트 언어가 준수해야 하는 규칙, 세부사항, 지침에 해당된다.

    자바스크립트가 넷스케이프 외 브라우저에서 사용됨에 따라 표준화를 위해 만들어졌으며, 다른 스크립트 언어들도 포함되어있다.

    즉, Javascript와 ECMAScript는 서로가 서로를 기반으로 하는 셈이다.

     

    비유하자면,

    • 국립국어원 === Ecma International
    • 국어(표준어) === ECMA-262
    • 맞춤법 등 규칙 === ECMAScript

    📒 ES6(ES2015)

    드디어, ES6를 시작해야 할 때다! 먼저, 아래는 ECMAScript의 출시연혁이다. 이를 보면, 2015년 출시한 ES의 6버전을 확인할 수 있다.

    출판일 이름 이전 판과의 차이점
    1 1997/6   초판
    2 1998/6   ISO/IEC 16262 국제 표준과 완전히 동일한 규격을 적용하기 위한 변경.
    3 1999/12   강력한 정규 표현식, 향상된 문자열 처리, 새로운 제어문 , try/catch 예외 처리, 엄격한 오류 정의, 수치형 출력의 포매팅 등.
    4 버려짐   4번째 판은 언어에 얽힌 정치적 차이로 인해 버려졌다. 이 판을 작업 가운데 일부는 5번째 판을 이루는 기본이 되고 다른 일부는 ECMA스크립트의 기본을 이루고 있다.
    5 2009/12   더 철저한 오류 검사를 제공하고 오류 경향이 있는 구조를 피하는 하부집합인 "strict mode"를 추가한다. 3번째 판의 규격에 있던 수많은 애매한 부분을 명확히 한다.[3]
    5.1 2011/6   ECMA스크립트 표준의 제 5.1판은 ISO/IEC 16262:2011 국제 표준 제3판과 함께 한다.
    6 2015/6 ES2015 6판에는 클래스와 모듈 같은 복잡한 응용 프로그램을 작성하기 위한 새로운 문법이 추가되었다. 하지만 이러한 문법의 의미는 5판의 strict mode와 같은 방법으로 정의된다. 이 판은 "ECMAScript Harmony" 혹은 "ES6 Harmony" 등으로 불리기도 한다.
    7 2016/6 ES2016 제곱연산자 추가, Array.prototype.includes
    8 2017/ 6 ES2017 함수 표현식의 인자에서 trailing commas 허용, Object values/entries 메소드, async/await 등.
    9 2018/6 ES2018 Promise.finally, Async iteration, object rest/spread property 등.
    10 2019/6 ES2019 Object.fromEntries, flat, flatMap, Symbol.description, optional catch 등.

     

    ES6는 ES5의 문제들을 해결하고, 기존 코드를 더 간결하게 작성하는 새로운 문법들이 추가되면서 가독성과 유지보수성이 향상되었다.

    덕분에 웹에서 사용하는 자바스크립트 라이브러리들의 개발환경도 ES6로 바뀌게 되었다. (lodash, React, Vue 등)

     

    📒 ES6 주요 변경점

     

    - 트랜스파일러를 사용한 크로스 브라우징 지원

    먼저, ES6가 지원되지 않는 구형 브라우저들이 존재한다. (IE6 과 같은)

    이러한 브라우저들도 사용할 수 있도록 ES5로 번역하는 과정을 트랜스파일링 이라고 한다. 대표적인 트랜스파일러가 바벨(Babel) 이다.

    // ES6
    const callName = (person) => {
      console.log(`Hey, ${person.name}`);
    };
    
    // ES5 트랜스파일링
    "use strict";
    
    var callName = function callName(person) {
      console.log("Hey, " + person.name);
    };

     

    - Arrows(Arrow Function, 화살표 함수)

    화살표 함수는 함수표현식의 축약형이라고 할 수 있다. "=>" 문법을 활용하며, C#, Java8, CoffeeScript 과 문법적으로 유사하다.

    이를 통해 상당히 간결하게 함수를 선언할 수 있다.

    const foo = function(x,y) { return x + y };
    const bar = (x, y) => x + y; 

     

    화살표 함수는 일반 함수와는 다른 특성이 있으며, 이에 따른 사용에 유의사항이 따른다.

    • 무조건 익명이다. 그렇기 때문에 함수선언만으론 활용할 수 없으며, 함수 표현식으로서 활용되며 변수에 할당되야한다.
    • 함수 매개변수에 default 값 적용이 가능하다. (x = 1, y) => x + y
    • 사용된 곳의 상위 스코프를 this로 가리킨다.(Lexical) <=> 일반 함수는 자신을 호출한 객체를 가리킨다.(Dynamic)
    • 위 특성으로 인해, 객체의 메서드로 사용불가(객체가 아닌 사용환경에 바인딩), 이벤트 리스너의 콜백함수로도 사용불가하다.(이벤트 DOM 상위 컨텍스트에 바인딩)
    • prototype 이 없다. 그렇기에, 객체의 생성자 함수로 사용할 수 없다.

     

    - Class (클래스 문법)

    ES6는 프로토타입의 객체기반 언어이다. 그렇기에, Java와 같은 클래스 패턴을 직관적으로 사용하기 위해 지원된 문법이다.

    클래스 패턴을 더 쉽고 단순하게 생성할 수 있다. 하지만, 클래스 자체의 원리로 설계되는 것이 아닌 모방의 형태임을 명심해야 한다.

    // ES5 생성자 함수와 인스턴스
    function Car (brand, owner) {
      this.brand = brand;
      this.owner = owner;
    }
    
    Car.prototype.sell = function (newOwner) {
      this.owner = newOwner;
    };
    
    const car = new Car('Kia', 'Ken');
    car.sell('wan');
    // ES6 클래스 문법과 인스턴스
    class Car {
      constructor(brand, owner) {
        this.brand = brand;
        this.owner = owner;
      }
    
      sell(newOwner) {
        this.owner = newOwner;
      }
    }
    
    const car = new Car('Kia', 'Ken');
    car.sell('wan');

     

    특히, Class는 함수와 달리 호이스팅이 적용되지 않으므로, 인스턴스 생성 전에 가장 먼저 선언을 해주어야 한다.

     

    - Enhanced Object Literals (개선된 객체 리터럴)

    1) 짧아진 객체 리터럴 : key 텍스트와 value 변수명이 같은 경우, 한번만 입력하면 된다. (콜론 : 입력 소요가 없어짐)

    // ES5
    var iPhone = '아이폰';
    var iPad = '아이패드';
    var iMac = '아이맥';
    
    var appleProducts = {
      iPhone: iPhone,
      iPad: iPad,
      iMac: iMac
    };
    
    // ES6
    const iPhone = '아이폰';
    const iPad = '아이패드';
    const iMac = '아이맥';
    
    const appleProducts = {iPhone,  iPad,  iMac};

     

    2) 축약형 메서드 이름 : 객체의 메서드를 정의할 때, function [함수명] 으로 선언하면 해당 함수명을 바로 key 값으로 반영한다.

    // ES5
    var dog = {
      name: 'Lycos',
      bark: function () {
        console.log('Woof! Woof!')
      }
    };
    
    dog.bark(); // 'Woof! Woof!';
    
    // ES6
    const dog = {
      name: 'Lycos',
      bark() {
        console.log('Woof! Woof!')
      }
    };
    
    dog.bark(); // 'Woof! Woof!';

     

    3) 계산된 값 사용 가능 : ES5는 객체를 생성한 뒤 [] 접근자로 프로퍼티 할당을 했지만, ES6는 객체의 키로 바로 적용 가능하다.

    // ES5
    var ironMan = 'Iron Man';
    var captainAmerica = 'Captain America';
    
    var MarvelHeros = {};
    
    MarvelHeros[ironMan] = 'I`m the Iron Man.';
    MarvelHeros['Groot'] = 'I am Groot.';
    MarvelHeros[captainAmerica] = 'My name is Steve Rogers.';
    MarvelHeros['3-D' + 'MAN'] = 'I`m the 3-D Man!';
    
    // ES6
    const ironMan = 'Iron Man';
    const captainAmerica = 'Captain America';
    
    const MarvelHeros = {
      [ironMan]: 'I`m the Iron Man.',
      ['Groot']: 'I am Groot.',
      [captainAmerica]: 'My name is Steve Rogers.',
      ['3-D' + 'MAN']: 'I`m the 3-D Man!'
    }

     

    - Template Literals (Template Strings)

    문법적으로 더 편하게 string을 생성할 수 있게 해준다. 백틱(``)으로 작성하며, 안에 ${} 를 통해 자바스크립트 작성이 가능하다.

    이를 통해, 기존에 string과 변수를 +로 이어붙인다거나, common-tags 같은 템플릿 엔진이나 라이브러리를 사용하지 않아도 된다.

    // ES5
    var brandName = 'TOAST';
    var productName = 'UI';
    
    console.log('Hello ' + brandName + ' ' + productName + '!'); // 'Hello TOAST UI!';
    
    // ES6
    const brandName = 'TOAST';
    const productName = 'UI';
    
    console.log(`Hello ${brandName} ${productName}!`); // 'Hello TOAST UI!';

     

    - Destructing (비구조화 할당)

    배열과 객체에 패턴 매칭을 통해 데이터 바인딩을 제공한다. 각 프로퍼티의 자리에 변수를 선언하면서, 쉽게 값을 할당할 수 있다.

    특히, 비구조화 할당은 실패에 유연하기 때문에, 매칭되지 않는 변수에 대해서는 자동으로 undefined가 할당된다.

    function printUserInformation(data) {
      const {name, age, gender, hobbies} = data;
      const [firstHobby] = hobbies; 
    
      console.log(`이름: ${name}`);
      console.log(`나이: ${age}`);
      console.log(`가장 좋아하는 취미: ${firstHobby}`);
    }
    
    console.log({
      name: "taeng",
      age: 29,
    })
    
    // 이름: taeng
    // 나이: 20
    // 가장 좋아하는 취미: undefined

     

    - Default, Rest, Spread

    먼저, 함수 파라미터에 기본값(default)을 설정할 수 있다. Redux reducer를 사용해본 사람들은 초기상태를 할당해보아 익숙할 것이다.

    function f(x, y=12) {
      // y is 12 if not passed (or passed as undefined)
      return x + y;
    }
    f(3) // 15

     

    또한, 전개 연산자(Spread)를 통해 배열을 나열할 수 있으며, 해당 문법으로 매개변수의 Rest 파라미터를 배열로 할당할 수 있다.

    const arr = [1, 2, 3, 4, 5];
    
    console.log(arr);		// [1,2,3,4,5]
    console.log(...arr);		// 1 2 3 4 5
    function f(x, ...y) {
      // y is an Array ["hello", true]
      return x * y.length;
    }
    f(3, "hello", true) // 6

     

    - let, const

    ES5까지는 var로 변수를 선언했음을 알 수 있다. 특히, 상수(불변) 변수를 선언할 방법이 없다보니 컨벤션(_변수명) 을 활용했다고 한다.

    이러한 기능을 지원하고자, 또 var 선언이 가지고 있는 문제점들을 개선하고자 새로 등장한 키워드가 let, const 이다.

     

    1) 블록 스코프 지원

    var 는 함수 레벨 스코프, let/const 는 블록 레벨 스코프를 가진다. 블록 레벨은 함수뿐만 아니라, 반복문/조건문/try-catch 까지 포함된다.

    좀 더 정교한 스코프 제한 속에서 의도치 않은 변수 수정을 방지할 수 있는 것이다.

    // ES5 : 콘솔 정상출력(같은 함수 스코프 안이므로)
    function sayHello(name) {
      if (!name) {
        var errorMessage = '"name" parameter should be non empty String.';
        
        alert(errorMessage);
      }
      
      console.log('Hello, ' + name + '!');
      console.log(errorMessage); // '"name" parameter should be non empty String.'
    }
    
    
    // ES6 : 에러 발생(변수는 조건문 스코프이므로)
    function sayHello(name) {
      if (!name) {
        let errorMessage = '"name" parameter should be non empty String.';
        
        alert(errorMessage);
      }
      
      console.log('Hello, ' + name + '!');
      console.log(errorMessage); // ReferenceError
    }
    

     

    2) 호이스팅 개선

    // ES5
    here = '여기야~';    // 변수 초기화가 먼저 되있지만 에러가 발생하지 않는다.
    
    console.log(here); // '여기야~'
    
    var here;          // 변수 선언은 이부분에 있다.
    
    
    // ES6
    here = '여기야~'; // ReferenceError - 변수 here 가 선언되지 않았다.
    
    console.log(here);
    
    let here;

    우선 var 변수 선언문은 호이스팅이 된다. 그럼, let/const 는 호이스팅되지 않기 때문에 ReferenceError가 발생하는걸까? 정답은 No!

     

    먼저, Javascript 변수의 원리에 대해 알 필요가 있다. 변수에는 총 3가지 동작단계가 있다.

    1. 선언 단계 : 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알림
    2. 초기화 단계 : 값을 저장하기 위해 메모리 공간을 확보. 암묵적으로 undefined를 할당하면서 초기화
    3. 할당 단계 : "=" 을 통해 대입하는 값이 있을 경우, 해당 변수에 값을 할당

    var는 선언, 초기화가 동시에 호이스팅되기 때문에 에러가 발생하지 않는다.

    하지만, let/const는 선언만 호이스팅이 발생하며, 초기화는 할당부분(=) 에서 발생한다.

    그 사이에 변수에 접근하면 에러가 발생하게되는 것이며, 이 사이구간을 TDZ(Temporal Dead Zone) 이라 칭한다.

     

    * howdy 님의 블로그(변수개념 관련) : www.howdy-mj.me/javascript/var-let-const/

     

    3) 변수 재선언, 재할당

    • 재선언 : var는 같은 변수명으로 재선언이 가능(최근값이 반영), let/const는 같은 변수명으로 재선언이 불가하다.
    • 재할당 : var, let은 변수에 값을 재할당 가능(가변), const는 변수에 값을 재할당할 수 없다.(불변)

     

    - Iterator, for - of 문

    ES6에 추가된 Iteration Protocol 은 for - of 반복문, 전개 연산자 등 순회동작을 하는 객체를 정의하기위한 일종의 규약이다.

     

    반복가능한 JS의 내장객체들을 iterable 객체라고 한다. (Array, TypedArray, String, Map, Set 등) 

    이들은, [Symbol.iterator]() 함수가 내장되어 있으며, 이는 Iterator를 반환한다. 이 조건을 Iterable Protocol 이라고 한다.

     

    위를 통해 반환된 Iterator는 2가지 조건을 가진다. 1) next() 메서드 포함, 2) 그 반환값은 { value: 요소값, done: 반복완료(boolean) }

    위 조건이 Iterator Protocol 이며, Iterable + Iterator Protocol 을 모두 만족하는 것이 Iteration Protocol 이다.

     

    이 Iteration Protocol 을 만족하는 객체들에 for - of 반복문이나 전개 연산자 등 문법이 적용 가능하다. (Object는 is not iterable 에러 발생)

    const arr = [1,2,3];
    const obj = { one: 1, two: 2, three: 3 };
    
    for (let val of arr) {
      console.log(val);
    }
    // 1 2 3
    
    for (let val of obj) {
      console.log(val);
    }
    // Uncaught TypeError: obj is not iterable

     

    - Generator

    Generator 함수는 직접 Iterable 객체를 만들기 위해 도입된 함수이다. function* 키워드로 선언, yield 로 반복요소를 지정할 수 있다.

    Generator 함수의 반환값은 iterable 객체이기 때문에, next(), throw() 와 같은 메서드를 적용할 수 있다.

    function* gen() {
      yield 1;
      yield 2;
      yield 3;
      yield 4;
    }
    
    const g = gen();
    
    console.log(g.next().value); // 1
    console.log(g.next().value); // 2
    console.log(g.next().value); // 3
    console.log(g.next().value); // 4
    console.log(g.next().value); // undefined

     

    * Iteration Protocol, Generator 포스팅 : abangpa1ace.tistory.com/34

    // ES5
    
    // ES6

     

    - Modules

    Javascript 모듈 개발이 가능하다. 모듈의 정의는 "한 프로그램의 일부이자, 독립적인 기능과 역할을 가진 단위" 라고 이해하면 된다.

    ES5까지는 CommonJS, AMD, RequireJS 와 같은 비공식 모듈 스펙을 사용해왔으며, Webpack 등 번들링 절차가 필수적이었다.

    ES6부터는 모듈개념을 통해 간결한 문법(import, export) 을 통해 모듈화와 상호간의 연동이 가능해졌다.

     

    자바스크립트 모듈은 .js 확장자 파일에 해당하며, 기본적으로 strict mode로 동작한다. 이제, 모듈연동을 위한 Import, Export를 알아보자.

     

    1) Named Export, Default Export

    // Named
    export const student = 'Park';
    export const student2 = 'Ted';
    
    const student3 = 'Abby';
    export {student3};
    
    // Default
    export default 'Jack'

    위처럼 default 키워드 유무에 따라 export 속성이 달라진다. 특히, Default Export는 한 파일에서 1개 모듈만 가능하다.

     

    2) Named Import

    // 1) 모듈명 그대로 가져오기
    import {student, student2, student3} from 'students.js';
    
    console.log(student);   // "Park";
    console.log(student2);  // "Ted";
    console.log(student3);  // "Abby";
    
    // 2) 변수명을 수정하여 가져오기
    import {student as park, student2 as ted, student3 as abby} from 'students.js';
    
    const student = 'Kim';
    
    console.log(student); // "Kim"
    console.log(park);    // "Park"
    console.log(ted);     // "Ted"
    console.log(abby);    // "Abby"
    
    // 3) 전체를 객체형태로 가져오기
    import * as students from 'students.js';
    
    console.log(students.student);  // "Park"
    console.log(students.student2); // "Ted"
    console.log(students.student3); // "Abby"

     

    3) Default Import

    import jack from 'studentJack';
    
    console.log(jack); // "Jack"

    디폴트는 중괄호 없이 가져올 수 있으며, 사용하고자 하는 모듈명을 as 없이 바로 사용해도 자동으로 반영이 된다. (모듈이 1개이기 때문)

    아래처럼, Named, Default Import 를 동시에 적용할수도 있다.

    import jack, {student, student2, student3} from 'students';
    
    console.log(jack);    // "Jack"
    console.log(student); // "Park"
    console.log(student2);// "Ted"
    console.log(student3);// "Abby"

     

    - Map, Set

    연상배열의 개념으로 Map, Set 이라고 하는 객체들이 지원된다. 객체와 비슷하나, 순서가 기억되는 Iterable 객체라는 차이가 있다.

     

    1) Map

    Map은 Object 처럼 key-value 형태로 데이터를 저장하는 객체이다. 다만 순서를 기억하는 iterable 이며, 아래 메서드들을 지원한다.

     맴버

    기능 

     size

         Map 객체 내의 요소들 수를 반환 

     set ( key , val )

         키 key / 값 val 요소를 추가 (중복될 경우에는 덮어씀) 

     get ( key )

         지정한 키가 갖고 있는 값을 획득 

     has ( key )

         지정한 키의 요소가 존재하는지 판독 

     delete ( key )

         지정한 키의 요소를 삭제 

     clear ( )

         모든 요소를 삭제 

     keys ( )

         모든 키를 취득 

      values ( )

         모든 값을 취득 

        entries ( )

         모든 키 / 값을 취득 

    forEach(fnc , [,that ])

         맵 내의 요소를 함수 fnc로 순서대로 처리 

    let car = new Map( );
    
    car.set( 'toyota' , '캠리' );
    car.set('volvo' ,'s80' );
    car.set('ferrari' ,'superfast 812' );
    
    console.log(car.size);                          // 결과: 3
    console.log(car.get('toyota'));              // 결과:  캠리
    console.log(car.has('ferrari'));              // 결과: true
    
    for( let key of car.keys( ) ) {
      console.log( key );                        //결과: toyota, volve, ferrari
    }
    
    for( let value of car.values( ) ) {
      console.log( value );                     //결과:  캠리, s80, superfast812
    }
    
    for( let [ key, value ] of car ) {
      console.log( value );                    //결과: 캠리, s80, superfaset812
    }
    
    car.delete( 'toyota' );
    console.log(car.size);                        // 결과: 2
    
    car.clear( );
    console.log( car.size );                     //결과: 0

     

    2) Set

    Set은 값(values)으로만 이루어진 Map 객체라고 생각하면 된다. (배열처럼 index 접근불가)

    또한, 중복되는 값을 생략하는 특성이 있다. 그렇기에, 내 경우엔 알고리즘에서 배열의 중복값을 없애기 위해 자주 사용해왔다.

     맴버

    기능 

     size

         Set 객체 내의 요소들 수를 반환 

     add (val)

         지정한 값을 추가

     has (val)

         지정한 값이 존재하는지 판정 

     delete (val)

         지정한 값의 요소를 삭제

     clear ( )

         모든 요소를 삭제

    entries ( )

         모든 키/값을 취득

    values( )

         모든 값을 취득

     forEach(fnc , [,that ])

         지정한 함수를 Set의 각 값마다 처리

    let data = new Set( );
    
    data.add(30);
    data.add(12);
    data.add(100);
    data.add(65);
    data.add(3);
    data.add(30);	// 중복값 미반영
    
    console.log(data.has(3)); //    결과: true
    console.log(data.size);    //     결과: 5
    
    for( let val of data.values( ) ){
      console.log(val);                   //  결과 : 30, 12, 100, 65, 3
    }
    
    for(let val of data){
      console.log(val);                  //  결과: 30, 12, 100, 65, 3
    }
    
    data.delete(3);      
    console.log(data.size)               //  결과: 4
    
    data.clear( );
    console.log(data.size)              // 결과: 0

     

    3) WeakMap, WeakSet

    이들은 new, has(), get(), set(), delete() 만 지원하는 축약형이라고 생각하면 된다.

     

    - Promise(프로미스)

    비동기 처리가 추상화된 객체이다. 말 그대로 객체이기 때문에, 결과값 외에도 비동기 처리상태나 조작 메서드 등을 지원하는 장점이 있다.

    특히, 이전 비동기 처리를 위한 콜백함수의 연계에 따른 콜백지옥의 문제점(가독성 불량, 디버깅 어려움) 을 해소하기 위한 문법이다.

     

    // ES5
    doSomething(function(result) {
      doSomethingElse(result, function(newResult) {
        doThirdThing(newResult, function(finalResult) {
          console.log('Got the final result: ' + finalResult);
        }, failureCallback);
      }, failureCallback);
    }, failureCallback);
    
    
    // ES6
    doSomethingPromise
      .then((result) => doSomethingElse(result))
      .then((newResult) => doThirdThing(newResult))
      .then((finalResult) => console.log('Got the final result: ' + finalResult))
      .catch(failureCallback);

     

    * async/await

     

    async 함수는 ES6 이후 버전(기억이 맞다면 2017년) 에 다시 한번 새롭게 지원된 비동기 문법이다.

    기존의 Promise 메서드 체이닝을 await 문법을 통해 좀 더 직관적으로(선언문 flow) 작성할 수 있으며, try/catch 문도 적용할 수 있다.

    // Promise
    function fetchMemberNames(groupId) {
      return getMemberGroup(groupId)
        .then(memberGroup => getMembers(memberGroup))
        .then(members => members.map(({name}) => name))
        .catch(err => {
          showNotify(err.message);
        });
    }
    
    fetchMemberNames('gid-11')
      .then(names => {
        if (names) {
          addMembers(names);
        }
      });
      
      
    // Async/Await
    async function fetchMemberNames(groupId) {
      try {
        const memberGroup = await getMemberGroup(groupId);
        const members = await getMembers(memberGroup);
    
        return members.map(({name}) => name);
      } catch (err) {
        showNotify(err.message);
      }
    }
    
    fetchMemberNames('gid-11')
      .then(members => {
        if (members) {
          addMembers(members);
        }
      });

     

    - 자료형 신규 메서드

    Number.EPSILON
    Number.isInteger(Infinity) // false
    Number.isNaN("NaN") // false
    
    Math.acosh(3) // 1.762747174039086
    Math.hypot(3, 4) // 5
    Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
    
    "abcde".includes("cd") // true
    "abc".repeat(3) // "abcabcabc"
    
    Array.from(document.querySelectorAll('*')) // Returns a real Array
    Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
    [0, 0, 0].fill(7, 1) // [0,7,7]
    [1, 2, 3].find(x => x == 3) // 3
    [1, 2, 3].findIndex(x => x == 2) // 1
    [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
    ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
    ["a", "b", "c"].keys() // iterator 0, 1, 2
    ["a", "b", "c"].values() // iterator "a", "b", "c"
    
    Object.assign(Point, { origin: new Point(0,0) })

     

    이외에도, Symbol 객체, Proxy 기능, Binary/Octal numeric 리터럴, Tail Calls(호출스택 초과방지) 등의 기능들이 신규로 지원되었다.


    이전부터 ES6에 대해 꼭 정리해보고 싶었고, 면접 전을 타겟으로 잡았으나 생각보다 많이 늦어졌다.

     

    신규문법을 정리하면서 느낀 점은, 내가 정말 당연하게 사용해온 기능과 편의성들이 ES6를 통해 개선되었다는 것이다!

    아마, import/export 전에는 module.exports() 문법을 썻을 것이며, var의 불편함이나, 전개 및 비구조화가 없는 불편함을 겪었을 것이다.

     

    또한, let/const, Promise, arrow function 등 이전과 달라진 문법이 등장한 배경, 차이점 등 개념을 학습하여, 사용하면 안되는 경우도 인지하게 된 뜻깊은 포스팅이 되었다! 🤩🤩🤩

    추후, ES2015 이후 매년 출시된 버전에서의 신규문법에 대해서도 다시금 정리해볼 생각이다.

     

     

    [출처]

    - Javascript W3Schools : www.w3schools.com/js/js_es6.asp

    - galid1 님의 블로그 (스크립트언어 관련) : galid1.tistory.com/193

    - 권경덕 님의 블로그 : jsdev.kr/t/es6/2944

    - Toast UI 님의 블로그 : ui.toast.com/fe-guide/ko_ES5-TO-ES6

    반응형
Designed by Tistory.