2.1 블록 수준 스코프

Last updated 10 months ago

ES5까지의 자바스크립트에는 변수 선언을 위하여 사용할 수 있는 수단이 var 키워드 뿐이였다. 자바스크립트의 변수 선언은 다른 프로그래밍 언어에 익숙한 이들에게 많은 혼란을 선사하곤 하는데, 가장 큰 두 이유는 바로 함수 수준 스코프호이스팅이다.

함수 수준 스코프

함수 수준 스코프란, 단어 자체에서 짐작할 수 있듯 모든 변수 선언이 함수 수준에서 이루어짐을 의미한다. 즉, 자바스크립트에서 코드 블록({...})은 새로운 스코프를 생성하지 않는다.

function foo() {
var abc = 123;
if (true) {
var abc = 456;
}
console.log(abc);
}
foo(); // 456

블록 수준의 스코핑을 지원하는 언어에서는 if 블록 바깥에서 콘솔에 찍어본 abc의 값은 123으로 남아 있을 것이다. 하지만 자바스크립트는 해당 코드를 감싸고 있는 가장 가까운 함수 (또는 전역) 가 달라질 때에만 새로운 스코프가 생성된다. 따라서 2번 라인과 4번 라인의 abc는 동일한 변수를 가리킨다.

if 블록을 새로운 함수로 대체 했을 때에는 예상 대로의 결과가 나오는 것을 확인할 수 있다.

function foo() {
var abc = 123;
function bar() {
var abc = 456;
}
console.log(abc);
}
foo(); // 123

호이스팅

호이스팅이란 변수의 선언과 초기화가 동시에 이루어졌을 때, 자바스크립트 인터프리터가 변수의 선언을 함수의 맨 위로 이동시키는 동작을 뜻한다.

function foo() {
console.log(bar); // undefined
var bar = 123;
}

bar 라는 변수를 선언 전에 참조하는 이러한 코드는 많은 언어에서 에러를 일으킬 것이다. 하지만 자바스크립트에서는 이 함수는 정상적으로 실행되며 콘솔엔 undefined가 찍힌다. 자바스크립트 엔진이 해당 함수를 아래와 같이 함수 시작점에 선언이 있고 이후 초기화되는 식으로 해석하기 때문이다.

function foo() {
var bar;
console.log(bar); // undefined
bar = 123;
}

블록 수준 스코프

자바스크립트의 이 두 독특한 동작 방식은 많은 프로그래머에게 혼란을 미쳐 왔다. ES6는 이러한 혼란을 피할 수 있도록 letconst이라는 새로운 변수 선언 키워드를 도입했다. 두 키워드를 사용해 새로운 함수가 만들어질 때와 더불어 대괄호({ ... }) 로 감싼 블록마다 생성되는 블록 수준 스코프의 지배를 받는 블록 수준 변수를 정의할 수 있다.