앞서 Closure를 말하기 전에 Scope와 Scope chain에 대해 먼저 살펴 보겠습니다.
스코프는 변수, 함수 및 객체의 범위(접근성)와 생존 기간을 정의하는 개념으로 변수나 함수가 선언되는 위치에 의해 결정이 됩니다.
변수를 사용한 예제
let num = 1; // 전역 스코프
{
let num = 2; // 지역 (블록)스코프
}
-------------------------------------
{
let num = 1; // 지역 (블록)스코프
}
{
let num = 2; // 지역 (블록)스코프
}
--------------------------------------
에러
let num = 1;
let num = 2;
함수를 사용한 예제
let num = 1; // 전역 스코프
function scopA() {
let num = 2; // (지역)함수 스코프 A
console.log(num);
}
function scopB() {
let name = "Ryan"; // (지역)함수 스코프 B
console.log(num);
}
scopA();
// scopA 함수의 콘솔로그는 자신의 지역 스코프에 num이 있기 때문에 2을 출력 합니다.
scopB();
// 하지만 scopB는 자신의 지역 스코프에 num이 없기 때문에 범위를 한 단계 더 넓혀 전역 스코프의 num인 1을 출력하게 됩니다.
-------------------------------------------------------------------------
let num = 1; // 전역 스코프
function scopA() {
let num = 2; // (지역)함수 스코프
console.log(num);
}
scopA();
// 이 또한 위와 같이 2을 출력 합니다.
console.log(num);
// 하지만 이 콘솔로그는 1을 출력하게 됩니다.
// 그 이유는 자신이 바라보는 시점에 있습니다.
// 현재 콘솔로그 기준으로 범위를 보면 scopA 함수의 num은 없는 존재이기 때문에 전역 스코프의 num만 확인할 수 있게 됩니다.
-------------------------------------------------------------------------
let num = 1; // 전역 스코프
function outer() {
let num = 2; // (지역,전역)함수 스코프 outer
function inner() {
let num = 3; // (지역)함수 스코프 inner
console.log(num + "inner"); // 3 출력
}
inner();
console.log(num + "outer"); // 2 출력
}
outer();
console.log(num + "global"); // 1 출력
-------------------------------------------------------------------------
에러
let num = 1; // 전역 스코프
function outer() {
let num = 2; // (지역,전역) 스코프 outer
function inner() {
let num = 3; // (지역)함수 스코프 inner
console.log(num + "inner");
}
console.log(num + "outer");
}
inner();
// inner is not defined
// inner 함수를 찾을수 없다는 오류가 납니다.
// 조금 전에 이야기했듯 함수 호출 및 콘솔로그 기준으로 {} 중괄호 내부에 있는 내용들은 찾을 수 없습니다.
outer();
console.log(num + "global");
위와 같이 스코프는 전역 스코프와 지역 스코프로 나뉘게 되며, 전역 스코프는 함수 외부 혹은 {}(블록) 외부에 선언된 변수나 함수로 어디서든 접근이 가능 합니다. 하지만 지역 스코프는 함수 내부 혹은 {}(블록) 내부에 선언된 변수나 함수로 해당 함수 내부 혹은 중괄호 내부에서만 접근이 가능합니다.
그렇다면 스코프 체인이란 무엇일까요?
스코프 체인은 변수를 찾을 때 자신이 속한 스코프에서부터 찾는 변수가 있는 스코프까지 차례로 한 단계식 올라가며 찾는 방식을 이야기합니다.
주의할 점은 앞서 코드블럭에서 이야기했듯 상위 스코프에서 하위 스코프에 선언된 변수로는 접근할 수 없습니다.
클로저(Closure)
클로저는 외부함수의 변수에 접근할 수 있는 내부 함수를 뜻 합니다.
const outer = () => { // 외부 함수
const num = 1;
const inner = () => { // 내부 함수
console.log(num);
}
return inner;
}
const fuc = outer();
fuc();
위의 코드를 살펴보면 outer 함수는 inner 함수를 return 하고 생을 마감하기 때문에 outer 함수의 변수 num 또한 더 이상 유효하지 않게 되어 변수 num에 접근하는 방법이 없습니다.
하지만 위의 코드를 실행해 보면 콘솔 로그에 1이 찍히게 됩니다.
이처럼 자신을 포함하고 있는 외부 함수보다 내부 함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부 함수가 호출되더라도 외부 함수의 지역 변수에 접근할 수 있는 함수를 클로저(Closure)라고 합니다.
그런데 이미 outer 함수의 num 변수는 유효하지 않게 되었는데 어떻게 1이 나올 수가 있게 되었을까요?
그 이유는 외부 함수가 이미 생을 마감하였더라도 외부 함수 내의 변수 num은 자신을 필요로 하는 내부 함수가 하나 이상 존재하는 경우 계속 유지되는 것입니다. 또한, 이때 불러온 변수는 복사본이 아니라 실제 변수에 접근한다는 것을 꼭 유의해 주세요
'프로그래밍 > JavaScript' 카테고리의 다른 글
자바스크립트 코드레시피 278 책 후기 (0) | 2023.05.04 |
---|---|
자바스크립트 함수 표현식&선언문과 화살표 함수 (0) | 2023.04.18 |