
식별자가 유효한 범위 또는 식별자를 검색할 때 사용하는 규칙.
변수나 함수, 함수의 매개 변수 등과 같은 식별자는 선언된 위치가 중요.
=> 식별자 참조 여부가 결정됨.
스코프를 통해 식별자의 이름 충돌을 방지할 수 있음.
=> 다른 스코프 내에서 같은 이름의 변수 사용 가능. (네임 스페이스)
🚨 자바스크립트는 같은 스코프내에 중복 선언을 허용하는 var와 같은 예외가 있음.
전역 / 지역 스코프
| 정의 | 참조 | |
|---|---|---|
| 전역 | 코드 가장 바깥 영역 | 전역 변수는 어디서든지 참조 |
| 지역 | 함수 몸체 내부 | 지역 변수는 자신의 스코프와 하위 스코프에서 참조 가능 스코프 체인으로 참조할 변수를 검색 |
스코프 체인
스코프가 상위 스코프와 하위 스코프를 갖으며 단방향으로 계층적으로 연결된 것.
=> 함수의 중첩으로 계층적 구조를 갖음.
🚨 단방향이므로 상위에서 하위 스코프의 변수를 참조할 수 없음
함수 레벨 스코프
지역 스코프라고도 할 수 있으며 자바스크립트의 var로 선언된 변수는 함수 코드 블럭만을 지역 스코프로 인식.
🧷 let과 const는 블록 단위로 지역 스코프를 생성.
📍아래 예제를 통해 var 변수 스코프에 대해 살펴보고 문제점을 확인하자.
// 전역에 var 변수 선언 및 할당.
var color = 'red';
if(typeof color === 'string'){
// 블럭문 안에서 var 변수 선언 및 할당.
var color = 'blue';
}
console.log(color); // blue
🧐 함수 레벨 스코프를 가지는 var로 선언된 변수는 위와 같이 블록 레벨 스코프를 인정하지 않아 전역변수로 재할당된다. 이는 의도치 않은 할당이 일어난 것이므로 코드를 구현하면서 예상치 못한 문제에 직면할 수 있음을 알 수 있다.
// 변수 선언 및 할당
const color = 'coral';
// 함수 선언문
function outerFunc(){
const color = 'skyblue';
innerFunc();
}
// 함수 선언문
function innerFunc(){
console.log(color);
}
outerFunc(); // coral
innerFunc(); // coral
🧐 outerFunc에 중첩된 innerFunc이 outerFunc의 color를 참조할 것이라고 예상할 수도 있을 것이다. 하지만 자바스크립트는 함수의 정의 시점에 스코프를 결정함으로 호출 시점과 상관없다는 것을 기억하자!
// 즉시 실행 함수(IIFE)
const color = (function(){
let color = 'red';
const init = () => {
color = 'red';
return color;
}
const setColor = newColor => {
color = newColor;
return color;
}
return { init, setColor }
})();
// 반환된 객체 값이 color1 변수에 할당.
const color1 = color;
console.log(color1.setColor('purple')); // purple
console.log(color1.init()); // red
🧐 위와 같이 클로저를 구현하면 참조하고 있는 렉시컬 환경이 살아있기 때문에 값을 참조하고 변경할 수 있다. 또한 반환된 함수들을 통해서만 변수에 접근할 수 있기 때문에 해당 변수는 은닉화할 수 있다.
딥다이브를 2번째로 읽으면서 글로 정리가 될 만큼 1번째보다 이해가 수월하다고 느낀다. 1번째는 해당 개념들이 있다는 것에 더 초점이 맞혀졌는데 2번째 읽으면서 이 개념들이 왜 필요한지에 대해 더 생각해 본 거 같다. 앞으로도 딥다이브를 2-3번...여러번 읽으면서 자바스크립트에 대해 자세히 알아가보자.
참고 자료
이웅모, 모던 자바스크립트 Deep Dive, 위키북스,