함수와 함수가 선언되었을 당시의 렉시컬 환경 조합이다.
이게 뭔소리야 할텐데 선언 당시 변수나 정보들을 기억하는 것이라고 생각하면 된다.
생명주기가 끝난 외부 함수의 변수에 접근할 수 있다.
const x = 1;
function outer() {
const x=10;
function inner() {
console.log(x);
}
inner(); // 10
}
outer();
위 코드에서 outer 함수 내 inner 함수가 실행되면 10이 출력되는 것을 알 수 있다.
스코프 체인으로 인해 inner 함수가 실행되기 전, 변수 정보를 받아와 출력한다.
const x = 1;
function outer() {
const x=10;
inner(); // 1
}
function inner() {
console.log(x);
}
outer();
다음 코드는 1이 출력된다.
outer 함수 내에서 inner 함수를 호출했는데에도 불구하고, 왜 10이 아닌 1이 나왔냐면 스코프가 서로 다르기 때문이다.
함수는 어디서 호출되었는지가 아닌 정의된 곳 기준에 따라 스코프가 결정된다는 것을 알 수 있다.
const x = 1;
function outer() {
const x=10;
const inner = function() {
console.log(x);
}
return inner;
}
const innerFunc = outer();
innerFunc();
외부 함수보다 중첩 함수가 더 오래 유지되는 경우, 중첩 함수는 이미 생명주기가 종료한 외부 함수의 변수를 여전히 참조할 수 있다.
여기서 중첩함수가 클로저이다.
위 코드에서 inner가 중첩함수이자, 클로저이다.
은닉이 큰 목적이라고 한다.
변수에 접근해서 중간에 값을 가로채고, 변경한다면 문제가 될 수 있다.
let num=0;
const increase = function(){
return ++num;
}
console.log(increase()); // 1
num = 100;
console.log(increase()); // 101
console.log(increase()); // 102
예시 코드를 보면, 중간에 값을 쉽게 변경할 수 있다는 것을 알 수 있다.
const increase = (function inc() {
let num = 0;
return function () {
return ++num;
}
})();
console.log(increase()); // 1
num = 100;
console.log(increase()); // 2
console.log(increase()); // 3
위 코드가 실행되었을 때 즉시실행 함수가 호출되었고, increase에 함수가 할당된다.
increase에 할당된 함수는 상위 스코프인 즉시실행 함수의 num변수를 기억하고 즉시실행 함수는 소멸된다.
따라서 num은 초기화되지 않으면서도 외부에서 접근할 수 없는 변수가 된다.