지금까지 스코프는 변수의 범위라고 알고 있었기 때문에 다 안다고 생각했었다.
근데 어떤 자료를 읽다보니 렉시컬 스코프(?) 라는 단어를 보고 다시 공부해야 되곘다 싶어 공부해 봤다...
scope의 한국어 뜻은 범위이다
뜻 자체로 scope는 변수에 접근할 수 있는 범위이다.
자바스크립트에는 전역, 지역 변수가 있다.
📌 어차피 이제 var
는 안쓰니까 let
으로 (블록레벨 스코프)로 설명하겠다.
let a = "global";
function localFunc() {
let a = "local";
a = "change value";
console.log(a);
}
localFunc(); // 1
console.log(a); // 2
위 코드를 보면
let
은 블록레벨 스코프를 따르는 변수이기 때문에 {}
내부에 있는 변수를 지역변수로 칭한다.
그래서 위 코드의 결과는
1️⃣ localFunc() -> "change value"
2️⃣ console.log(a) -> "global" 이다
let a = "global";
function localFunc() {
a = "change value";
console.log(a);
}
localFunc(); // 1
console.log(a); // 2
방금 코드에서 지역변수 a를 선언을 안했다고 생각해보자
그럼 결과는
1️⃣ localFunc() -> "change value"
2️⃣ console.log(a) -> "change value" 이다
📌 이것처럼 같은 범위내에 가져오려는 변수가 없으면 변수를 찾을 때 까지 외부 범위로 나가는 걸 스코프 체인이라고 한다.
❗️내부 범위로는 절대 못가고 외부에도 변수가 없으면 변수를 찾지 못했다는 에러가 발생한다.
❓ 그래서 내가 처음들어봤던 렉시컬 스코프는 뭐냐
우선 가장 중요한 개념이 있는데 ❗️스코프는 함수를 호출할 때가 아니라 선언할 때 생긴다❗️
이게 무슨 말이냐면 아래 코드를 보면 된다.
분명 내 생각으로는 log()가 wapper 내부에서 호출되기 때문에 wrapper 내의 name을 참조하지 않을까? 라고 생각했다.
그럼 결과가 nero여야 하는데 zero네?
이게 바로 렉시컬 스코프다.
무슨말이냐면 스코프는 함수를 선언할 때 생기기 때문에 log 함수를 선언할때 name 변수를 찾을텐데 현재 블록 범위에 없기 때문에 외부의 전역변수 name을 참조하게 되는거다.
그래서 이미 전역변수 name을 사용하기로 마음먹었기 때문에 wrapper 내부에서 호출해도 전역변수를 사용한다.
👍 드디어 렉시컬 스코프가 뭔지 알아냈다. 근데 log가 wrapper의 지역변수 name을 참조하게 할 수는 없을까 했는데 이건 실행 컨텍스트(?)를 이용하면 된다고 한다.
전역변수는 변수가 섞이게 될 수도 있기 때문에 지양하라고 하기 때문에 최대한 블록 범위를 작게 해서 변수를 선언해야 겠다.
그리고 실행 컨텍스트도 공부해야겠다...
참고 : https://www.zerocho.com/category/JavaScript/post/5740531574288ebc5f2ba97e
모던 자바스크립트 deep dive