[ES6] let과 const

2019. 10. 12. 09:55Programming/모던 자바스크립트 개발을 위한 ES6 수강내용 정리

반응형

모던 자바스크립트 개발을 위한 ES6

이 포스팅은 인프런의 '모던 자바스크립트 개발을 위한 ES6 강좌'의 수강 내용을 바탕으로 정리한 내용입니다.

Scope

ES6에서는 변수를 선언하기 위한 키워드 letconst가 추가됐습니다. 이번에는 이 letconst가 기존의 var과 어떤 차이를 가지는 지, 그리고 왜 letconst를 사용해야 하는지에 대한 내용을 정리합니다.

varfunction, with, catch 키워드를 사용했을 경우에만 유효한 scope를 생성하게 됩니다. 아래의 코드를 살펴봅시다.

var array = [1, 2, 3];
for(var i=0; i<array.length; i++){}
console.log(i);

if(array) {
  var last = array.pop();
}
console.log(last);

위의 코드에서 console.log(i)console.log(last)는 각각 3을 출력하게 됩니다. 일반적으로 변수의 유효범위(Scope)는 {}를 기준으로 생각하게 되는데, var을 사용하게 되는 경우 function, with, catch를 사용할 때만 변수의 유효범위가 새로 정의되게 되므로 생각치도 못한 오동작이 발생할 경우가 생깁니다. 아래의 HTML코드를 확인해봅시다.

<ul>
    <li>Hello0</li>
    <li>Hello1</li>
    <li>Hello2</li>
    <li>Hello3</li>
</ul>

<scriprt>
var list = document.querySelectorAll("li");

for(var i=0; i<list.length; i++) {
  list[i].addEventListener('click', function() {
    alert(i);
  })
}
</script>

li의 항목을 클릭하면, 몇 번째 li인지 인덱스를 alert로 출력하는 코드입니다. for구문 내에서 선언된 i의 유효범위가 {}를 기준으로 생각하면, li를 클릭할 때마다 인덱스가 제대로 출력되야 합니다. 하지만 실제로 코드를 돌려보면 몇 번째 li를 클릭하더라도 4가 출력됩니다. i의 스코프가 {}를 따르지 않기 때문이며, ES5에서 이는 클로저를 사용하여 해결이 가능합니다. 다만 클로저는 사용이 끝난 변수에 대한 참조가 남아있는 한 할당된 메모리가 해제되지 않으므로, 메모리 누수를 발생시킬 소지가 있습니다.

클로저를 사용하여 문제를 해결하게 될 경우 코드는 아래와 같이 작성하게 됩니다. 메모리 누수의 발생 가능성같은 여부는 차치하고서라도, 즉시 호출 함수에 대한 이해가 없으면 코드를 파악하는데 혼란이 올 수도 있습니다. 즉시 호출 함수를 사용하지 않는 경우에는 함수를 추가로 작성하여 코드를 한 눈에 파악하기 어렵고, 매번 코드를 확인할 때마다 해당 함수를 쫓아가야 가는 경우도 생길 수 있습니다.

var list = document.querySelectorAll("li");
for(var i=0; i<list.length; i++) {
  list[i].addEventListener('click', (function(index) {
      return function(){
      alert(index);
    }
  })(i));
}

letconst는 변수의 유효범위가 {}를 따르게 됩니다. 따라서 위와 같은 코드에서는, for문 내에서 i를 선언할 때 let 키워드로 선언함으로써 클로저를 사용하지 않고도 문제를 해결할 수 있습니다. 게다가 코드가 좀 더 직관적으로 변하게 됩니다. 다른 언어를 사용하던 사람도, let을 사용하여 변수를 선언하게 되면 코드를 파악하는데 좀 더 쉬워집니다. 따라서 ES6를 사용할 수 있는 환경이라면, var 대신 let을 사용하도록 합시다.

<ul>
    <li>Hello0</li>
    <li>Hello1</li>
    <li>Hello2</li>
    <li>Hello3</li>
</ul>

<scriprt>
let list = document.querySelectorAll("li");

for(let i=0; i<list.length; i++) {
  list[i].addEventListener('click', function() {
    alert(i);
  })
}
</script>

const로 선언한 값들은 상수로서, 이후에 변경이 불가능한(immutable) 값으로 선언하게 됩니다. const로 선언된 값을 재선언하거나, 값을 변경하려고 할 경우에는 스크립트 에러가 발생합니다. 일반적으로는 const를 사용하고 값을 변경할 필요가 있을 경우에만 let을 사용함으로써, 코드에 대한 직관성을 높일 수 있습니다.

const MY_FAV = 7;
const MY_FAV = 20; //스크립트 에러 발생
MY_FAV = 20; //스크립트 에러 발생
let MY_FAV = 20; //스크립트 에러 발생

const와 불변성(immutability)

const를 사용하여 Array객체를 생성한 뒤, pushpop을 사용해보면 객체 내부에 값이 변경되는 것을 확인할 수 있습니다.

const arr = [1, 2, 3];
arr.push(4);
console.log(arr); //(4)[1, 2, 3, 4]
arr.pop();
console.log(arr); //(3)[1, 2, 3]

const는 선언에 대한 내용만 재선언이 불가능할 뿐, 불변성을 보장해주지는 않는다는 것을 알 수 있습니다. const 키워드를 사용하여 객체를 선언하더라도, 객체 내부 값들에 대한 속성의 선언 방식에는 영향을 미치지 않기 때문입니다. :)

[참고]:
let, MDN web docs
const, MDN web docs
ECMA-262, Indexed Collections > Array Objects

반응형