변수 이름, 함수 이름, 클래스 이름과 같은 식별자가 본인이 선언된 위치에 따라 다른 코드에서 자신이 참조될 수 있을지 없을지 결정되는 것 → ‘유효범위’
스코프가 계층적으로 연결되어 있는 것을 ‘스코프 체인’ 이라고 한다. ( 스코프체인은 아래에서 위로 단방향성이다.)
변수를 참조할때 자바스크립트 엔진은 스코프체인을 통해 변수를 참조한다. 코드가실행된 지역의 스코프안에 참조하려고 하는 식별자를 찾을때까지 스코프체인을 통해 타고타고 올라간다. 전역 스코프에도 원하는 식별자를 찾을 수 없으면 참조에러가 난다.
대부분의 프로그래밍 언어는 함수나,if문,for문 모두 코드 블록이 지역스코프를 만든다 → 블록 레벨 스코프
자바스크립트에서는 var키워드로 선언된 변수는 오로지 함수 블록만이 지역스코프를 만든다. → 함수 레벨 스코프
자바스크립트에서도 블록 레벨 스코프를 가지고 싶어함. → let ,const ( ES6 ) 도입
→ let 과 const 키워드로 선언된 변수는 for문이나 if문의 코드 블록안에서도 지역스코프를 만들 수가 있다.
자바스크립트는 렉시컬 스코프( 정적 스코프 ) 를 따르기 때문에 함수가 정의되는 시점에 즉, 소스코드 평가 과정에서 상위 스코프가 결정이 된다. 그리고 해당 함수에 의해 함수 객체가 생성이 되면 해당함수의 객체는 본인의 상위 스코프를 항상 알 수 있게 된다.
→ 어떻게 알 수 있는가? 자바스크립트에서는 함수는 정의되는 시점에 자신의 내부슬롯에 상위 스코프의 참조를 저장하기 때문이다.
렉시컬 환경 : 어떠한 코드가 어디서 실행이 되고 본인 주변의 어떤 코드들이 있는지 대체적인 정보를 담고있는 환경이라고 할 수 있음.
함수가 호출 → 실행 컨텍스를 생성하고 콜스택에 푸시함 → 함수 자신의 렉시컬 환경 생성 ( 포함하는 식별자, 식별자에 바인딩 된 값, 상위 렉시컬 환경에 대한 참조 ) → 코드의 실행이 끝나면 콜스택에서 해당 실행컨텍스트를 pop하여 제거한다.
const x = 1;
function out() {
const x = 10;
const inner = function() {
console.log(x);
};
return inner;
}
const ethan = out();
ethan(); // 10
// 참조가 가능하다.
어떻게 out함수가 실행이 종료되면서 out함수 안에서 선언된 x변수의 생명주기가 끝났음에도 불구하고 inner함수안에서 x를 참조할 수 있었을까?
생명주기를 마감한 외부함수의 지역변수를 참조할 수 있다면 이때 이 함수를 클로져 라고 한다.
이 위에서 inner() 함수가 클로져가 된다.
클로져에 의해 참조된 변수를 자유변수라고 한다.
이러한 클로져는 하나의 state가 의도치 않게 변경되지 않도록 state를 안전하게 은닉하고 또는 특정 함수에게만 state 변경을 허용하기 위해 사용함
추가 : let,const는 블록안에서도 지역스코프(local)를 만든다.
참고자료 출처