본문 바로가기
Language/Javascript

ES6 주요 문법 정리 (2) let/const, Iterators, Generators, Unicode, Modules

by joooing 2021. 1. 8.
반응형

지난번 글에서는 ES6문법이 무엇이고 왜 사용하는지에 대해 간략히 소개하고 문법 중 일부인 Arrows, Classes, Enhanced Object Literals, Template Strings, Destructuring, Default Parameter, Rest, Spread 에 대해 살펴봤다. 이어서 이번에는 아래 표시한 부분들을 소개해보려 한다. ES6의 주요 문법을 정리하는 글은 이 글을 마지막으로 하고 여기서 소개하지 못한 나머지 개념들은 중요하거나 필요하다고 생각되면 하나씩 따로 블로깅할 예정이다.

let, const


변수 선언 키워드인 let, const도 ES6 문법 중 하나이다. ES5까지는 오직 var을 통해서만 변수를 선언할 수 있었다고 한다..🙉 새삼 이 시대에 자바스크립트를 배우게 되어 다행이라는 생각도 든다.. 이 둘에 대해 자세히 알고 싶다면 이 글을 먼저 보고 오는걸 추천한다. 여기선 Scope, 재할당같은 단어들에 대한 설명은 생략하려 한다. let과 const는 기존에 Function Scope를 따르던 var과는 달리 Block Scope를 따라 변수를 선언하도록 한다.

 

✔️ Function Scope = function(){ } 함수로 구분된 영역

✔️ Block Scope = {중괄호}로 구분된 영역

 

아래 예시를 통해 var, let, const의 차이점을 Scope와 재할당 가능 여부 위주로 살펴보자. 한 번 결과를 예상해보면서 이해했는 지 확인해보는 것도 좋은 방법일 것 같다.

 

// var
function varTest() {
    var x = 1;
    
    if (true) {
        var x = 2;         // 위와 같은 x임
        console.log(x);    // 2
    }

    console.log(x);        // 2
}

 

// let
function letTest() {
    let x = 1;
    
    if (true) {
        let x = 2;         // 위와는 다른 x임
        console.log(x);    // 2
        x = 3;
        console.log(x);    // 3 (재할당 성공)
    }
    
    console.log(x);        // 1
}

 

// const
function constTest() {
    const x = 1;
    
    if (true) {
        const x = 2;       // 위와는 다른 x임
        console.log(x);    // 2
        x = 3;
        console.log(x);    // error(재할당 실패)
    }
    
    console.log(x);        // 1
}

 

 

 

Iterators + for...of


이 부분도 자세하게 설명하려면 글이 길어질 것 같아 간략히만 소개하고 넘어가려 한다. 지난번에 두 개의 글로 나누어 적어둔 적이 있어서 아래 링크된 글들을 먼저 보는걸 추천한다.

👉🏻 Iterators 👉🏻 For ...Of

 

Iterators

 

✔️Iterable(객체가 '반복' 가능한 조건)의 요소들을 순회하기 위한 '포인터'이며 next()함수를 가진 객체, 다시말해 '객체를 반복할 수 있게 하는' 객체이다.

✔️객체가 순서대로 나열될 수 있는 조건 (= 객체의 원소들이 '순서대로' 불려지는 규칙)

✔️ next() 함수를 가진 객체

 

 

for ...of

 

for ...of 반복문은 ES6에 추가된 새로운 컬렉션 전용 반복 구문입니다. for ...of구문을 사용하기 위해선 컬렉션 객체가 [Symbol.iterator] 속성을 가지고 있어야만 합니다(직접 명시 가능).

✔️ 반복 가능한 객체(iterable)를 순회할 수 있도록 해줌

✔️ Array, Map, Set, arguments 등이 해당됨 (Object는 해당 X)

 

 

 

 

Generator (제너레이터)


ES6에는 Generator라는 비동기 프로그래밍을 위한 기능도 있다. 제너레이터를 사용하면, 함수 실행을 잠시 멈췄다가 필요할 때 다시 실행시킬 수 있다. Generator은 Iterator의 반대라고 생각해볼 수 있다. Iterator는 값을 '읽어오기' 위해 사용하고, Generator는 값을 '쓰기' 위해 사용하기 때문이다.

 

Generator는 function* 으로 정의된 함수를 호출해서 얻어지는 객체를 의미한다 그렇게 만들어진 함수 객체는 객체는 이터러블(iterable) + 이터레이터(iterator)이다. Iterator의 특징 중 하나가 next() 메서드를 포함하는 것이기 때문에, Generator로 얻는 객체 또한 next() 메서드를 포함한다. 그리고 return과 비슷한 역할을 하는 yield라는 연산자를 사용한다. 결과값을 반환하는 형식이 return과는 다른데, yield는 value속성의 객체를 만들고 이 속성 안에 결과값을 넣어서 돌려준다.

 

✔️ function* : 제너레이터 함수 정의

✔️ next() : 제너레이터 함수 실행 시작

✔️ yield : value속성의 객체를 만들고, 이 안에 결과값을 넣어서 반환해줌

 

위의 개념들을 바탕으로 Generator 함수가 어떻게 동작하는지 살펴보자. 일반적인 함수와는 다르게 Generator 함수는 next() 메서드가 호출되어야 함수 실행이 시작된다. 그리고 처음으로 만나는 yield에 값을 전달하고 실행을 멈추게 된다. 그 후 다시 next()가 호출되면 멈춘 위치부터 실행을 시작해 다음 yield를 만날 때까지 실행되다가 또 멈춘다. 아래 예시를 보면 알 수 있듯이 next() → yield → next() → yield ... 이런 반복 과정은 return을 만나거나 마지막 라인이 실행될 때까지 진행된다. 

 

function* gen() {
  yield 1;
  yield 2;
  yield 3;
  return 4;
}

const iter = gen();
console.log(iter.next());  // {value:1, done:false}
console.log(iter.next());  // {value:2, done:false}
console.log(iter.next());  // {value:3, done:false}
console.log(iter.next());  // {value:4, done:true}

 

function* gen() {
  yield 1;
  yield 2;
  yield 3;
}
// 제너레이터를 순회하며 값을 읽음
for (let i of gen()) { 
  console.log(i);
}
// 1 2 3

 

 

 

Unicode


유니코드는 '전 세계 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 하나의 표준'이다. 유니코드라는 하나의 데이터베이스에는 우리가 사용하는 어떤 기호든지 특정 숫자(코드포인트)가 지정되어 있기 때문에 매칭시킬 수 있다. 덕분에 기호를 실제로 사용하지 않고도 'A' → 'U+0041' 이런 식으로 쉽게 표현할 수 있다. 여기로 가보면 유니코드들을 검색해볼 수 있는데 무려 원숭이한테까지도.. U+1F649 같은 코드가 있었다.. 궁금하면 들어가서 아무거나 검색해보자! 진짜 없는게 없다.

 

 

코드포인트는 보통 0을 붙여 최소 네자리의 16진수로 표현하며 앞에 U+를 붙인다. 쉽게 말해 U+0000부터 U+10FFFF까지의 값을 사용하는 것이다. 이제 Javascript에서는 어떻게 사용하는 지 살펴보자. 아래 예시에서 첫글자인 '원'의 유니코드는 'U+C6D0'이다. 자바스크립트 문자열에서는 '\uc6d0'으로 표현할 수 있다. 앞에 백슬래시(\)를 붙이고 뒤에 문자/숫자 조합을 적기만 하면 된다. 이렇게 백슬래시(\) 뒤에 문자나 숫자가 오는 조합을 이스케이프 시퀀스(escape sequence)라고 부르기도 한다.

 

그런데 기존(ES5..)에는 4자리의 16진수로 코드포인트를 표현한다는 한계가 있었다. 이게 바로 아래 코드의 결과부분을 보면 이모지 대신 ὤ9같은 이상한 기호가 나오는 원인이다ㅠㅠ 위에서 본 이모지( 🙉)의 코드는 U+1F649였다. 여기서 U+ 뒤에 달린 1F649 이 부분은 5자리이기 때문에, 4자리의 코드포인트만 표현할 수 있던 ES5는 이모지를 제대로 표시하지 못한 것이다.

 

'\uc6d0\uc22d\uc774\u1f649'
// 원숭이ὤ9

 

하지만 ES6에서는 유니코드 코드포인트 이스케이프라는 새로운 형식의 이스케이프 시퀀스를 도입해 이런 문제를 극복했다. 새로운 문법은 아래처럼 사용하는데, {중괄호} 안에 6자리까지 쓸 수 있어서 모든 유니코드 코드포인트를 넣을 수 있다. 따라서 5자리짜리 코드포인트를 가진 이모지도 정상적으로 출력이 된다. 새로운 ES6 문법을 사용하면 어떤 유니코드 기호도 간단하게 표시할 수 있게 된다.

 

'\u{c6d0}\u{c22d}\u{c774}\u{1f649}'
// 원숭이🙉

 

 

 

Modules (import, export)


모듈(Module)은 '애플리케이션을 구성하는 개별적 요소로서, 재사용 가능한 코드 조각'이다. 그냥 .js 확장자를 가진 파일 하나라고 생각하면 쉽다. 스크립트 하나가 모듈 하나이다. 이전에는 두 개의 파일을 연결해주려면 아래처럼 일일이 태그를 만들어서.. 적어줘야했다.

 

<script>
  src = "main.js";
</script>
<script>
  src = "sayHi.js";
</script>

 

하지만 ES6부터는 모듈에 export나 import같은 지시자를 적용하면, 다른 모듈을 현재 파일에 불러와서 그 안에 있는 함수나 변수를 호출하는 등 서로 공유를 할 수 있게 된다.

 

✔️ export = 모듈 내보내기 (외부 모듈에서 해당 변수나 함수에 접근 가능)

✔️ import = 외부 모듈 불러오기

 

// sayHi.js
export function sayHi(name) {
  console.log(`Hi!!! ${name}`);
}

 

// main.js
import {sayHi} from './sayHi.js';

sayHi('jooing'); // Hi!!! jooing

 

뿐만 아니라 ES6은 export default 나 export * 같은 문법들도 제공한다. export default는 '해당 모듈에는 하나의 개체만 존재한다’는 것을 나타내는 문법이다. (굳이 왜 개체가 하나만 존재하는걸 알리는지 궁금하다면 여기에 이유가 나와있다) export * 는 전체를 뜻하는 * 기호를 사용해 '한꺼번에 모듈의 모든 것을 가져온다'고 명시하는 문법이다.

 

✔️ export default = 해당 모듈에는 하나의 개체만 존재한다

✔️ export * = 모듈의 모든 것 가져오기

 

 

 

 

반응형

댓글