현재 실행되는 컨텍스트
Scope
란 현재 실행되는 컨텍스트이며 변수를 참조할 수 있는 유효한 범위를 뜻한다.
스코프는 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다.
스코프를 정리하면 다음과 같다.
변수를 참조할 수 있는 유효한 범위
식별자(변수, 함수, 클래스 이름)가 유효한 범위
블럭 안의 변수는 블럭 안에서만 유효
Code Block은 변수의 유효 범위 영역이다.
예를들어 코드의 { }
, if() { }
, for() { }
, function() { }
....등등을 뜻한다.
블럭 외부에서는 블럭 내부의 변수를 참조할 수 없다.
{
const a = 'a';
console.log(a); // a
}
console.log(a); // Error
또한 함수 외부에서는 함수 내부의 변수, 매개변수를 참조 할 수 없다.
function print() {
const message = 'Hello World'
console.log(message); // Hello World
}
console.log(message); // Error
function sum(a, b) {
console.log(a, b);
}
console.log(a, b); // Error
사용하지 않는 원시값, 객체, 함수... 등을 찾아 삭제
C
언어같은 저수준 언어에서는 메모리 관리를 위해 malloc()
과 free()
를 사용하여 개발자가 직접 메모리를 관리한다.
반면, 자바스크립트는 객체가 생성되었을 때 자동으로 메모리를 할당하고 더 이상 필요하지 않을 때 Garbage Collection
에 의해 자동으로 해제된다.
Garbage Collection
은 주기적으로 오브젝트 참조여부를 확인하여 참조하고 있지 않다면 메모리에서 삭제한다.
글로벌 변수는 앱이 종료될때까지 메모리에 유지된다.
그러므로 가급적 글로벌 변수의 사용을 금하되 변수는 필요한 블럭내에서만 사용하는 것을 권장한다.
// 글로벌 변수는 앱이 종료될때까지 계속 메모리에 유지
const global = 1;
{
// 블럭 내부에서만 존재, 블럭이 끝나면 자동 소멸(GC)
const local = 1;
}
function print() {
// 함수 내부에서도 블럭안에 필요한 경우, 필요한 곳에서 변수 선언 및 사용
if (true) {
let temp = 0;
}
}
스크립트 전체, 실행중인 함수, 코드블록 등이 갖는 자신만의 스코프
각각의 블록은 렉시컬 환경(Lexical Environtment)
이라는 내부 오브젝트를 포함하고 있다.
렉시컬 환경 오브젝트
는 블록의 선언된 변수, 인접한 부모의 정보...등등 다양한 정보를 포함한다.
렉시컬 환경
은 현재 블록에 정보를 담당하는 환경 레코드(Environment Record)
, 블록의 부모를 참조하는 외부 환경 참조 (Outer Lexical Environment Reference)
로 구성되어 있다.
스코프 체인(Scope Chain)
은 선언된 블록들이 부모의 렉시컬환경을 참조하는 것을 뜻한다.
기본적으로 블록은 종료되면 순서대로 실행 컨텍스트 스택에서 제거된다.
이 때 블록에서 사용하고자 하는 변수가 선언되있지 않다면 스코프 체인으로 연결된 부모 환경 레코드를 확인한다.
만약 스코프체인을 통해 변수를 자주 접근한다면 성능에 악영향을 준다.
선언된 코드를 최상단으로 끌어 올림
호이스팅(Hoisting)
은 사전적 의미로 끌어 올리다라는 뜻이다.
자바스크립트 엔진(번역기, Interpreter)
은 코드를 실행하기 전 변수, 함수, 클래스의 선언문을 끌어 올린다.
이 때 선언과 초기화 단계는 분리되어 선언만 코드의 최상단으로 끌어 올려진다.
함수 호이스팅
을 통해 함수의 선언문은 코드 최상단으로 끌어 올려져 함수 선언이전에도 호출을 가능하게 해준다.
단 함수 표현식은 호출이 불가능하다.
print1(); // hello
function print1() {
console.log('hello');
}
print2(); // Error
const print2 = function print() {
console.log('hello');
}
변수(let
, const
)와 클래스는 선언만 호이스팅되고 초기화는 되지 않는다.
그래서 초기화 전 변수에 접근하면 컴파일 에러가 발생한다.
console.log(hi); // Error
let hi = 'hi';
const cat = new Cat(); // Error
class Cat {};
기본적으로 자바스크립트에서 변수를 선언할 때는 let
, const
키워드를 사용한다.
하지만 es6
이전에는 주로 var
키워드를 사용해 변수를 선언했다.
지금은 사용되지 않지만 이전에 var
키워드를 사용한 코드를 읽기 위해서는 var
키워드의 특징은 알아두어야 한다.
var
는 변수 선언 키워드 없이 선언 & 할당이 가능// 선언, 재할당 구분 어려움
str = 'var';
console.log(str); // var
var
는 __중복 선언**_이 가능var str = 'var';
var str = 'var';
console.log(str); // var var
var
는 블록 레벨 스코프를 무시하고 함수 레벨 스코프만 지원var animal = 'panda';
{
var animal = 'cat';
{
var animal = 'dog';
}
}
console.log(animal); // dog
function example() {
var dog = 'dog';
}
console.log(dog); // Error
JavaScript 의 제한된 버전을 선택하여 암묵적인 "느슨한 모드(sloppy mode)" 를 해제하기 위한 방법
엄격 모드(strict mode
)는 ES5에 추가된 키워드이다. 사용하고자 하는 곳에 'use strict';
를 입력하여 사용한다.
엄격 모드는 자바스크립트가 묵인했던 에러들의 에러 메시지를 발생시킨다. 즉 엄격하게 문법을 검사를 하겠다는 의미다.
엄격 모드는 다음과 같은 특징이 존재한다.
'use strict';
var x = 1;
delete x; // Error
'use strict';
function add(x) {
var a = 2;
b = a + x; // Error
}
add(1);
'use strict';
function add() {
console.log(this); // undefined
}
add();
'use strict';
const arr = [1, 2, 3];
for (num of arr) { // num변수에 선언 키워드 생략해서 에러
console.log(num);
}
스코프 - 용어 사전 | MDN
자바스크립트의 메모리 관리 - JavaScript | MDN
호이스팅 - 용어 사전 | MDN
Strict mode - JavaScript | MDN
모던 자바스크립트 Deep Dive
모던 JavaScript 튜토리얼