ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS/ES2015] 자바스크립트 ES2015(ES6) 문법 정리(1) - let / const
    Frontend 2019. 5. 17. 23:14

    자바스크립트는 또 다른 말로 ECMA스크립트(ECMAScript, ES)라고도 불린다. ECMA스크립트는 Ecma 인터내셔널의 ECMA-262 기술 규격에 정의된 표준화된 스크립트 프로그래밍 언어이다. (라고 위키피디아에서 알려줬다.) Ecma 인터내셔널이란 곳에서 자바스크립트 공식문서를 만들고 표준화하는 작업을 하는 데, 이 과정은 모두 http://ecma-international.org/ 사이트에 공개되어 있다.

     

    하여튼 이 자바스크립트 언어도 연도별로 버전이 나눠져있는데, 우리가 지금 주로 사용하는 문법은 2015년 이전에 개발된 ES5 버전이다. 그리고 2015년에 ES6 버전이 나왔는데, 기존에 사용하던 문법과 많이 다른 새로운 형태의 문법들이 추가되었다. 예를 들면 화살표 함수라던가 let이나 const같은 변수, 상수라던가... 그리고 이 버전은 원래 ES6라는 이름으로 나왔다가 무슨 이유에선지 ES2015라는 이름으로 바뀌었다고 한다. 

     

    ES2015에서 바뀐 내용이 한두가지가 아니지만 일단은 가장 기본적이고 중요한 부분들을 정리해보려고 한다.

    오늘은 그 중에서도 가장 대표적인 파트인 letconst에 대해서 다룰 것이다.

     


     

    1. let

    자바스크립트에서 일반적으로 변수를 선언할 때는 var라는 키워드를 사용한다.

    var a = 1; 이라고 변수를 선언 및 할당했을 때, var a는 1이라는 값을 가지는 기억 공간을 말한다.

    이 a라는 공간에 집어넣을 수 있는 값은 계속해서 변할 수 있으므로 a를 변수라고 부른다.

     

    var a = 1;
    
    if (true) {
      var b = 2;
    }
    
    console.log(a + b); // 3

    위 코드에서 console.log(a + b);는 3을 출력하는 데,

    그 이유는 var로 선언한 변수는 스코프가 함수 단위로 결정되기 때문이다.

    변수 b는 어떤 함수 안에서 선언된 것이 아니라 단순히 if문 안에 선언되어 있으므로 전역변수이다.

    그러므로 전역변수 a와 b를 더하여 3을 출력하는 것이다.

     

    let c = 1;
    
    if (true) {
      let d = 2;
    }
    
    console.log(c + d);

    반면에 let은 함수 단위가 아닌 블록 단위로 스코프가 결정되는 변수이다.

    위 코드를 실행시키면 d is not defined라는 에러가 발생하는데, 

    그 이유는 d변수가 let으로 선언되었으며 if문 안에서 선언되었기 때문이다.

     

    for (let i = 0; i < 10; i++) {
      console.log(i); // 9
    }
    
    console.log(i); // i is not defined

    위 코드도 마찬가지의 이유로 에러가 발생한다.

    i변수를 for문 안에서 let으로 선언하였기 때문에

    for문 밖에서는 i에 접근할 수가 없다.

     

    let c = 1;
    {
      let d = 2;
    }
    console.log(c + d);

    그렇다면 만약에 if문이나 for문이 아닌 아무 의미없는 중괄호로 변수를 감싸게 되면 어떻게 될까?

     

    위 코드에서도 여전히 d is not defined 에러가 발생한다.

    아무 의미가 없다고 하더라도 {}로 감싸면 하나의 블록으로 인식되고

    그 내부에서만 d변수에 접근할 수 있다.

     

    var x = 'global';
    let y = 'global';
    
    console.log(this.x);  // "global"
    console.log(this.y);  // "undefinded" - global 객체에 붙지 않음

    let 변수의 또 다른 특징은 전역에 선언되어도 글로벌 객체에 붙지 않는다는 점이다.

    var로 선언된 변수 x를 this.x나 window.x로 출력하면 "global"이라는 값이 출력되지만

    let으로 선언된 변수 y는 undefined를 출력한다.

     

    function doSomething () {
      console.log(bar); // undefined
      console.log(foo); // ReferenceError : Cannot access 'foo' before initialization
      var bar = 1;
      let foo = 2;
    }
    doSomething();

    흥미로운 점은 let은 변수의 호이스팅을 어느 정도 막는다는 점이다.

     

    위 코드를 보면 bar 변수는 doSomething함수 스코프 내의 가장 최상단으로 끌어올려졌다.

    즉, 변수가 호이스팅되었고 또한 초기화되어 undefined 상태가 되었다.

     

    그러나, foo변수는 Reference Error가 출력된다.

    내용을 잘 읽어보면 초기화 전에 'foo'에 접근할 수 없다는 메시지가 출력된다.

     

    즉, foo변수가 아예 호이스팅이 되지 않은 것은 아니다.

    만약에 호이스팅이 되지 않았다면 아예 foo변수 자체를 인식할 수 없으므로

    foo is not defined라는 에러 메시지가 출력되었을 것이다.

     

    위 경우에는 foo변수가 호이스팅이 되긴 하였으나 초기화되지 않아

    let foo;라는 문장으로 초기화가 이루어지기 전에는 접근이 불가능하다.

     

    이렇게 let으로 선언된 변수가 호이스팅은 되었으나

    초기화되지 않아 접근할 수 없는 구역을 Temporal Dead Zone이라고 한다.

     

    let a = 1;
    let a = 2;
    console.log(a);	// Uncaught SyntaxError: Identifier 'a' has already been declared

    또한 let은 변수를 재선언하는 것이 엄격하게 금지된다.

    var 변수는 (비록 변수를 재선언하는 것은 매우 나쁜 습관이나) 변수의 재선언이 허용된다.

     

    즉 위 코드에서 let을 var로 바꾸면 console.log(a)는 에러가 발생하지 않고 마지막으로 할당한 값인 2가 출력될 것이다. 그러나 let 변수는 재선언을 매우 엄격히 금지하고 있으므로 오히려 나쁜 습관을 예방하는 데 도움을 준다고 할 수도 있겠다.

     

     

    2. const

    constconstant variable, 즉 불변의 값을 담을 때 사용하는 키워드이다.

    즉, 변수가 아니고 상수이다.

     

    const foo = 2;
    foo = 3; // Type Error: Assignment to constant variable

    const에 어떤 값이 할당되면 그 값은 변하지 않는 값이어야하기 때문에

    값을 재할당할 수 없게 된다. let과 같이 재선언 역시 엄격하게 금지된다.

     

    재할당을 하면 위와 같이 Type Error: Assignment to constant variable이란 에러메시지가 출력되고

    재선언을 하면 Uncaught SyntaxError: Identifier 'a' has already been declared란 에러메시지가 출력된다.

     

    const obj = {
      arr: [1, 2, 3];
    }
    
    obj = []; // 에러
    obj.arr = null; // 가능
    obj.arr.length = 0; // 가능
    obj.arr.push(1);  // 가능
    */

    위 코드를 살펴보자. obj에 객체를 할당하여 선언하였다.

    이 obj 상수에 빈 배열을 재할당하면 에러가 발생한다.

    const로 선언하면 재할당이 불가능하기 때문이다.

     

    그러나 obj.arr = null;이란 코드는 아무 문제없이 사용 가능하다.

    그 이유는 위 코드가 obj라는 상수를 재선언/재할당하는 것이 아니기 때문이다.

    위 코드는 obj가 만들어 낸 arr이라는 배열을 없애는 코드이므로 에러가 발생하지 않는다.

    obj.arr.length = 0;이나 obj.arr.push(1);이란 코드도 마찬가지이다.

     

    obj 객체 내부에 요소를 추가하거나 삭제하는 것은 아무런 문제가 되지 않는다.

     

     

     

      var let const
      변수 변수 상수
    재선언 가능 불가능 불가능
    재할당 가능 가능 불가능
    스코프 함수 단위 블록 단위 블록 단위

     

    반응형

    COMMENT