Lexical Environment & garbage collection
렉시컬 환경과 가비지 컬렉션 알고리즘🗑🗑
자바스크립트에서 실행 중인 함수, 코드블록 {...}, 스크립트 전체는 렉시컬 환경 이라 불리는 내부 숨긴 연관 객체(internal hidden associated object)를 갖습니다.
- 환경 레코드 - 모든 지역 변수를 프로퍼티로 저장하고 있는 개체입니다. this 값과 같은 기타 정보도 여기에 저장됩니다.
- 외부 렉시컬 환경에 대한 참조 - 외부 코드와 연관됨
"변수"는 특수 내부 객체인 환경 레코드의 프로퍼티일 뿐입니다. "변수를 가져오거나 변경"하는 것은 '환경 레코드의 프로퍼티를 가져오거나 변경’함을 의미합니다
변수를 변경하면 환경 레코드 프로퍼티가 변경됩니다.
아래 두줄짜리 코드엔 렉시컬 환경이 하나 존재합니다.
이렇게 스크립트 전체와 관련된 렉시컬 환경은 전역 렉시컬 환경(global Lexical Environment)이라고 합니다.
클로저 🎭
클로저는 외부 변수를 기억하고 이 외부 변수에 접근 할 수 있는 함수를 의미합니다. 숨김 프로퍼티인 [[Environment]] 를 이용해 자신이 어디서 만들어 졌는지를 기억합니다. 함수 내부의 코드는 [[Environment]]를 사용해 외부 변수에 접근합니다.
가비지 컬렉션 알고리즘 = 도달가능성이 없어질때 자동으로 삭제됨
함수 호출이 끝나면 함수에 대응하는 렉시컬 환경이 메모리에서 제거됩니다.
자바스크립트에서 모든 객체는 도달 가능한 상태일 때만 메모리가 유지된다.
그런데 호출이 끝난 후에도 여전히 도달 가능한 중첩 함수가 있을 수 있습니다.
아래 예시를 실행하면 3개의 렉시컬 환경이 만들어 지는데, 이는 메모리에서 삭제되지 않는다.
function f() {
let value = Math.random();
return function() { alert(value); };
}
// 배열 안의 세 함수는 각각 f()를 호출할 때 생성된
// 렉시컬 환경과 연관 관계를 맺습니다.
let arr = [f(), f(), f()];
내부 알고리즘 🔑
1. 가비지 컬렉터는 루트(root) 정보를 수집하고 이를 ‘mark(기억)’ 합니다.
2. 이후 루트가 참조하고 있는 것들을 mark 합니다.
3. 도달 가능한 모든 객체를 방문할 때까지, mark 한 객체가 참조하는 객체를 계속해서 mark 합니다.
4. 마지막으로 방문할 수 없었던 객체를 메모리에서 삭제합니다.
정리
- 가비지 컬렉션은 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없습니다.
- 객체는 도달 가능한 상태일 때 메모리에 남습니다.
- 참조된다고 해서 도달 가능한 것은 아닙니다. 서로 연결된 객체들도 도달 불가능 할 수 있습니다.
Reference
KoJavaScriptInfo