본 내용은 10분 테코톡 엘라님의 강의를 토대로 작성하였습니다.
1. 스코프
스코프란?
- 변수 이름, 함수 이름, 클래스 이름과 같은 식별자가 본인이 선언된 위치에 따라 다른 코드에서 자신이 참조될 수 있을지 없을지 결정되는 것
- JavaScript를 포함한 모든 프로그래밍 언어에서 기본적인 개념
- 전역에서 선언된 경우 -> 전역변수
- 전역 스코프를 가짐
- 지역에서 선언된 경우 -> 지역변수
- 지역 스코프를 가짐
스코프 체인
- 함수의 중첩: 함수는 전역에서 선언될 수도 있고 또다른 함수 내부에서 선언될 수 있음
- 중첩 함수: 함수 내부에서 선언된 함수
- 외부 함수: 중첩 함수를 포함하는 함수
- 함수가 중첩이 된다면 각각 함수의 스코프도 중첩이 됨 -> 스코프가 함수의 중첩에 의해 계층적인 구조를 가질 수 있음
- 스코프체인: 스코프가 계층적으로 연결되어 있는 것
- 스코프 체인은 물리적으로 존재
- 변수를 참조할 때 자바스크립트 엔진 스코프 체인을 통해 변수를 참조
- 변수를 참조할 때, 해당 스코프에 변수가 없으면 상위 스코프로 올라가 변수를 찾음
- 전역 스코프까지 연쇄적으로 변수를 찾음
- 전역 스코프에도 변수가 없으면 ReferenceError 발생
- 반방향성: 변수를 찾는 것은 상향으로 이뤄짐
let x = "전역변수x";
function outer() {
let y = "outer함수의 지역변수y";
console.log(x); // "전역변수x"
console.log(y); // "outer함수의 지역변수y"
function inner() {
let x = "inner함수의 지역변수x";
console.log(x); // "inner함수의 지역변수x"
console.log(y); // "outer함수의 지역변수y"
}
inner();
}
outer();
console.log(x); // "전역변수x"
console.log(y); // ReferenceError...
// 이 코드의 스코프 체인은 전역 스코프 > outer 지역 스코프 > inner 지역 스코프
스코프 종류(스코프 레벨)
- 블록 레벨 스코프
- if문, for문, 함수…
- 대부분의 프로그래밍 언어
- let, const(JavaScript)
- 함수 레벨 스코프
- only 함수
- var키워드(JavaScript)
스코프 종류(스코프가 결정되는 시점)
- 동적 스코프
- 함수가 호출되는 시점에 결정
- 프로그램 런타임 도중 실행 컨텍스트나 호출 컨텍스트에 의해서 결정
- 정적 스코프
- 함수가 정의되는 시점에 결정
- 렉시컬 스코프
- JavaScript는 이를 따름
- 함수가 생기자마자 상위 스코프가 결정이 되고 함수 객체가 생성이 되면 해당 함수 객체는 자신의 상위 스코프를 알 수 있음
- 자신의 내부 슬롯에 상위 스코프의 참조를 저장
함수 호출과 스코프
- 함수 호출
- 실행 컨텍스트 생성
- 실행 컨텍스트 스택에 push
- 함수의 렉시컬 환경 생성
- 렉시컬 환경: 포함하는 식별자, 식별자에 바인딩 된 값, 상위 레시컬 환경에 대한 참조
- 코드가 어디서 실행이 되고 본인 주변에 어떤 코드들이 있는지 대체적인 정보를 담고 있음
- 함수 실행
- 실행 컨텍스트 스택에서 해당 컨텍스트를 pop
2. 클로져
- 함수의 중첩에서 내부 함수가 생명주기를 마감한 외부 함수의 변수를 참조
- 이때의 내부함수를 클로져라고 함
- 클로져
- 한 중첩함수가 상위 스코프의 식별자를 참조하고 있고
- 본인의 외부 함수보다 더 오래 살아있는 경우
- 본인의 상위 스코프에서 참조하고 있는 식별자만 기억
- 자유변수: 클로저에 의해 참조된 변수
- 클로져는 하나의 state가 의도치 않게 변경되지 않도록 state를 안전하게 은닉하고 특정 함수에게만 state 변경을 허용하기 위해 사용
const x = 1;
// 중첩 함수 inner를 반환하면서 생명주기를 마감하는 함수, 이때 실행 컨텍스트 스택에서 제거
function outer() {
const x = 10; // outer의 생명주기가 끝나면 접근할 수 없음
const inner = function() { // 클로져
// 생명주기가 끝난 외부함수의 변수를 접근할 수 있음
console.log(x);
};
return inner;
}
const example = outer();
example(); // 10을 출력
클로져의 원리
- outer 생명 주기가 끝나 실행 컨텍스트 스택에서 제거
- outer 함수의 생명 주기가 종료되어도 해당 함수의 렉시컬 환경은 존재
- outer 함수는 inner함수를 반환하며 사라짐
- example 함수는 inner함수 객체를 참조
- inner함수는 자신의 내부 슬롯에 저장된 outer 함수의 렉시컬 환경을 참조
- 가비지 컬렉션의 대상이 되지 않음
- 그 결과, outer함수의 변수를 참조할 수 있게 됨
Reference
'programming study > JavaScript' 카테고리의 다른 글
ES6 - const & let (0) | 2021.10.19 |
---|---|
ES6 & Babel (0) | 2021.10.18 |
Generator & Iterator (2) - Generator (0) | 2021.10.11 |
Generator & Iterator (1) - Iteration Interface (0) | 2021.10.10 |
ES Modules (0) | 2021.09.28 |