Chapter 15
15.1 var 키워드로 선언한 변수의 문제점
15.1.1 변수 중복 선언 허용
- 의도치 않게 먼저 선언된 변수 값이 변경되는 부작용이 발생한다.
15.1.2 함수 레벨 스코프
- var 키워드로 선언한 변수는 오직 함수의 코드 블록만을 지역 스코프로 인정하기 때문에 함수 외부에서 선언하면 모두 전역 변수가 된다.
- for, if문 등에서 var로 선언한 변수도 모두 전역 변수가 된다.
15.1.3 변수 호이스팅
- var 키워드로 선언한 변수는 변수 선언문 이전에 참조할 수 있다. 이 때 참조하면 undefined를 반환한다.
호이스팅이 발생하는 이유?
- 자바스크립트에서는 변수 선언이 런타임에서 되는 것이 아니라, 그 이전 단계에서 먼저 실행된다. 자바스크립트에서 변수를 메모리에 할당하는 과정은 크게 3단계로 진행된다.
- 실행 컨텍스트 변수 객체에 등록하는 선언 단계
- 변수 객체에 대한 메모리 할당 및 변수를 undefined로 초기화하는 초기화 단계
- undefined로 초기화 된 변수에 값 할당하는 할당 단계
즉, 자바스크립트 엔진은 코드를 실행하기 전에 실행 컨텍스트에 등록된 변수 객체에 접근할 수 있다.
var의 경우 변수 선언과 초기화 단계가 함께 진행되어 변수 객체 등록과 동시에 메모리 공간도 할당 받는다. 메모리를 할당받은 상태이므로 메모리를 참조해서 변수에 접근이 가능하다.
실행 컨텍스트?
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
- 전역 공간에서 자동으로 생성되는 전역 컨텍스트
- 함수 실행에 의한 컨텍스트
• 실행 컨텍스트 객체는 활성화 되는 시점에 VariableEnviroment, LexcialEnvrionment, ThisBinding의 정보를 수집한다.
VariableEnviroment
- 현재 컨텍스트 내의 식별자(변수)들에 대한 정보, 외부 환경 정보, 선언 시점의 LexicalEnvironment의 스냅샷(변경사항 반영 X)정보를 포함한다.
LexicalEnvironment
- 처음에는 VariableEnvironment와 같다. 하지만, 함수 실행 도중에 변경되는 사항이 즉시 반영된다.
ThisBinding
LexicalEnvironment와 VariableEnvironment는 다음과 environmentRecord와 outerEnvironmentReference로 구성되어 있다.
environmentRecord
- 매개변수 식별자, 변수 식별자, 선언한 함수의 식별자 등을 수집한다.(호이스팅이라는 개념이 가능해진 이유)
outerEnvironmentReference
- 상위 컨텍스트의 LexcicalEnviroment 정보를 참조한다.(이를 기반으로 스코프가 형성되고, 스코프 체인을 통해 상위 컨텍스트에 접근할 수 있다.)
15.2 let 키워드
ES6에서 let과 const가 추가됐다.
15.2.1 변수 중복 선언 금지
- let 키워드로 이름이 같은 변수를 중복 선언하면 문법 에러가 발생한다.
15.2.2 블록 레벨 스코프
- let으로 선언한 변수는 if, for while문 등등 모든 코드 블록을 지역 스코프로 인정한다.
let a = 1;
{
let a = 2;
let b = 3;
}
console.log(a);
console.log(b);
위의 전역 스코프와 블록 스코프에 선언된 a 변수는 모두 다른 변수다.
15.2.3 변수 호이스팅
var는 선언과 초기화 단계가 동시에 진행되면서 호이스팅이 되고, const/let은 선언과 초기화 분리되어 진행되므로 선언 단계만 진행되면서 호이스팅이 되기 때문이다.
호이스팅이 된 시점에 var의 경우 변수에 undefined가 할당되어 있는 상태고, const/let은 undefined로 초기화되지 않았으므로 ReferenceError가 발생한다.
let으로 선언한 변수는 변수 호이스팅이 발생하지 않는것 처럼 보이지만, 호이스팅이 발생하기 때문에 참조 에러를 출력한다.
15.2.4 전역 객체와 let
- let 키워드로 선언한 변수는 전역 객체의 프로퍼티가 아니다.
- let 전역 변수는 위의 실행 컨텍스트에서 언급한 environmentRecord내에 존재하게 된다.
15.3 const 키워드
- const 키워드는 주로 상수를 선언하기 위해 사용한다.
15.3.1 선언과 초기화
- const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다.
const a;
15.3.2 재할당 금지
- const 키워드로 선언한 변수는 재할당이 금지된다.
15.3.3 상수
- 상수는 재할당이 금지된 변수를 말한다.
- const 키워드로 선언된 변수는 재할당이 금지되기 때문에 선언된 변수에 원시 값을 할당한 경우 immutable value가 된다. 할당된 값을 변경할수도 없다.
15.3.4 const 키워드와 객체
- const 키워드로 선언된 변수에 원시 값을 할당하면 값을 변경할 수 없지만, 객체를 할당한 경우 값을 변경할 수 있다.
- const 키워드는 재할당을 금지할 뿐, 불변을 의미하지 않는다.
const person = {
name: "jin"
}
person.name = 'won';
console.log(person);
15.4 var vs let vs const
- ES6를 사용한다면 var를 지양한다.
- 재할당이 필요한 경우에 한정해 let 키워드를 사용하고, 변수 스코프를 좁게 만든다.
- 변경이 발생하지 않고 읽기 전용으로 사용하는 원시 값과 객체에는 const 키워드를 사용한다.
참고사이트
https://junilhwang.github.io/TIL/Javascript/Domain/Execution-Context/