스코프 체인
스코프 체인이란
한마디로 정리하면 블록에서 어떤 값에 접근이 가능하고 어떤 값에는 접근이 불가능한지를 확인해주는 것이다.
이때 블록은 { }로 표현되는 if, while, for, try-catch... 등이 있고 그냥 { }만 작성해도 블록으로 처리된다.
아래 코드는 함수 b를 선언했지만 실제로 실행시키게 되면 b는 선언되지 않았다고 나온다. 왜일까?
const x = "x1";
function c() {
const y = "y";
console.log("C");
function b() {
const z = "z";
console.log(b);
c();
}
}
function a() {
const x = "x2";
console.log("a");
b();
}
a();
c();
함수의 선언위치를 살펴보면 알 수 있는데 a와 c는 js의 호출스택 기준으로 살펴볼 때 메인이라고 할 수 있는 anonymous 함수 안에 있다
a => anonymous c => anonymous
반대로 anonymous에서 안으로(a,c)는 접근이 불가능하다 안에서 밖으로만 접근이 가능
하지만 b는 c 함수 안에 먼저 포함되기 때문에. b => c => anonymous가 된다(함수 뿐만 아니라 변수도 포함된다, y도 마찬가지)
이러한 관계들은 코드를 실행시키게 되면 절대 바뀌지 않는데 이것을 렉시컬 스코프라고도 한다.
이때 a 함수로 가서 스코프를 살펴보기위해 선언만 살펴보게 되면 x => a => anonymous뿐이 없다.
a가 실행됐을 때 b()를 실행시키게 되는데 a안에는 b라는 선언문이 없고 a를 타고 anonymous로 갔을 때도 b를 찾을 수 없으니 undefined가 된다
사실 그림을 그려보면 쉽다
선언만을 생각해서 그려보면 아래 그림과 같다. 여기에 밖에서 안으로의 접근은 불가능하고 안에서 밖으로만 접근이 가능할 때 a 함수 내부에서 b라는 함수를 호출시키면 a 입장에선 자신의 블록 내부와 anonymous 블록 내부를 살펴봐도 b에 대한 정보는 없다.
따라서 a에서 호출하는 b는 에러가 뜬다
추가적으로 위 코드에서 x는 두번 선언 되어 있다.
마지막으로 응용해서 생각해보면
a에서 접근하는 x는 a 함수 내부에 있는 x이고 anonymous의 x와는 다르다.
a에 있는 x를 지우면 a함수에서는 anonymous에 있는 x에 접근할 수 있다.
하지만 anonymous에 있는 x를 지우면 anonymous는 a 함수 안에 있는 x를 접근할 수 없다
https://www.youtube.com/watch?v=0lF2zaQ31Ek&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=4