JavaScript에는 세가지 변수 선언 방법이 있다. 간단하게 요약하면 다음과 같다.
var
: function-scoped, globally-scoped 변수를 선언하고 초깃값을 설정할 수 있다.let
: block-scoped 변수를 선언하고 초깃값을 설정할 수 있다.const
: block-scoped 상수를 선언하고 초깃값을 반드시 설정해야 한다. 상수의 값을 재할당하거나 다시 선언할 수 없다.스코프란 현재 접근할 수 있는 변수들의 범위를 의미한다.
{}
으로 구분된다.var a = 1;
if (a) {
var b = 2;
}
function func() {
var c = 3;
}
console.log(a); // 1
console.log(b); // 2 : globally-scoped
console.log(c); // c is not defined
function varTest() {
var x = 1;
if (true) {
var x = 2; // 상위 블록과 같은 변수
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // 상위 블록과 다른 변수
console.log(x); // 2
}
console.log(x); // 1
}
var x = 'global';
let y = 'global';
console.log(this.x); // "global" 전역 객체의 속성 x를 생성
console.log(this.y); // undefined 전역 객체의 속성 y를 생성하지 않음
Lexical Environment
에 추가한다.Lexical Environment ?
식별자-변수값 쌍을 가지고 있는 자료구조이다.
식별자는 변수 또는 함수의 이름이다.
변수 값은 변수가 담고 있는 원시 값이나 오브젝트 참조(주소)를 뜻한다.
즉, 프로그램이 실행되는 동안 변수, 함수가 존재하는 공간을 의미한다.
Lexical Environment
의 개념적 구성은 다음과 같다.LexicalEnvironment = {
Identifier: <value>,
Identifier: <function object>
}
console.log(a); // undefined
var a = 3;
위 코드를 실행하면 3이 아니라 undefined가 출력된다. 이는 JavaScript 엔진이 var로 선언된 변수를 찾아 선언을 lexical environment에 넣으면서 값을 undefined로 초기화하기 때문이다. 그 후 변수가 선언된 위치에서 값을 할당한다면 그때 undefined가 다른 값으로 대체된다.
위 예제에서 변수 a에 3이 할당되기 전까지의 lexical environment를 나타내면 다음과 같다.
LexicalEnvironment = {
a: undefined,
};
console.log(a); //ReferenceError: a is not defined
let a = 3;
위 코드를 실행하면 ReferenceError
가 발생한다. 이는 JavaScript가 let, const로 선언된 변수를 선언만 끌어올리고 값을 초기화하지 않기 때문이다. JavaScript 엔진은 var로 선언된 변수와 달리 let, const로 선언된 변수를 찾아 lexical environment
에 넣으면서 값을 초기화하지 않는다. 따라서 변수 선언 위치보다 앞에서 해당 변수를 참조하면 ReferenceError
결과를 얻게 된다.
블록 내에서 변수 선언이 처리되기 전까지를 tdz(temporal dead zone)
상태 라고 부른다.
let 변수가 선언된 위치에서도 변수에 할당한 값을 찾을 수 없을 때에는 undefined를 할당한다.
const 변수의 경우 선언과 초깃값 설정이 동시에 이루어져야 하기 때문에 초깃값이 없다면 오류를 반환한다.
위 예제에서 변수 a에 3이 할당되기 전까지의 lexical environment를 나타내면 다음과 같다.
LexicalEnvironment = {
a: <uninitialized>
}
helloWorld(); // 'Hello World!'
function helloWorld() {
console.log('Hello World!');
}
helloWorld(); // TypeError: helloWorld is not a function
var helloWorld = function () {
console.log('Hello World!');
};