스코프는 식별자의 유효한 범위를 뜻한다.
var는 함수 블록만 스코프로 가진다.
스코프는 단 두가지다. 전역or지역.
const a = 5;
//전역스코프
{
//지역 스코프
const a = 6;
console.log(a);
}
// 출력은 6
변수를 참조할때 js엔진은 스코프 체인을 통해 변수를 참조하는 코드에서 시작해 상위 방향 스코프로 이동하며 변수를 찾아낸다.
=> 내부 스코프의 const a = 6
가 없다면, 5
가 출력된다.
이를 스코프체이닝이라 함.
클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생성 시 함수가 생성될 때마다 생성됩니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
바로 이해가 가진 않는다.
예시로 살펴보자.
const x = 1;
function outer(){
const x = 10;
inner();
}
function inner(){
console.log(x);
}
//...출력은 1
왜 출력이 1일까?
JS는 Lexcial Scope(정적 스코프)를 가지기 때문이다
=> 함수가 정의될 때의 환경을 가짐. 따라서 정의 될 당시 스코프체이닝에 의해 1
이 나온다.
이를 저장하는 슬롯이 함수의 [[Environment]]
슬롯이다. (함수는 사실 일급 객체임. 나중에 다뤄보자)
그렇다면 아래의 결과는 어떨까?
const x = 1;
function outer(){
const x = 10;
const inner = function() { console.log(x); }
return inner;
}
const innerFunc = outer();
innerFunc();
// 답 : ?
지금까지 배운 내용을 토대로 순서를 추측해보자.
inner
이 정의될때의 lexcial scope를 보면 x가 10이다 (inner의 environment슬롯에 10 할당)innerFunc
에 outer()
함수를 실행한 결과를 할당. outer()
함수는 여기서 생명주기가 끝난다.=> environmnet슬롯에 할당됨. outer의 컨텍스트가 제거되어도 내부함수의 지역변수가 살아있음
이를 클로저라 한다.
또한, outer()
함수의 실행 컨텍스트는 실행되어 제거됐지만, Lexical Environment는 남아있음.(정확히 말하면 inner함수의 [[environment]]슬롯이 참조중)
=> 참조중이기에, 가비지 컬렉터의 대상이 되지 않는다!
클로저를 활용하는법도 있지만, 중요한건 뜻하지 않은 결과를 내지 말기위해 배우는 것이다.