✅ 스코프 (Scope)
식별자가 유효한 범위
- 모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다.
1️⃣ 전역 스코프 (Global Scope)
함수나 블록에서 가장 바깥에 있는 영역
- 코드의 어느 부분에서든 참조가 가능하다.
2️⃣ 지역 스코프 (Local Scope)
함수나 블록 내부 등 특정 영역
- 자신이 위치한 지역 스코프와 하위 지역 스코프에서만 참조가 가능하다.
📍함수 스코프 (Function Scope)
함수 블록만 지역 스코프로 인정
- 함수 외 if, for, while, try/catch 등의 블록은 인정X
var x = 10;
if (true) {
var x = 42;
}
console.log(x); // 42
📍블록 스코프 (Block Scope)
모든 코드 블록을 지역 스코프로 인정
- 함수 외 {}, if, for, while, try/catch 등의 블록을 지역 스코프로 인정
- 블록 내부에 선언된 지역 변수는 블록 내부에서만 접근이 가능하다.
- JS는 함수 레벨 스코프를 따르는 언어이지만 ES6에서 let이 도입되면서 블록 스코프 사용이 시작되었다.
💡var : 함수에서만 지역 변수가 되는 함수 레벨 스코프
💡let, const : 모든 코드 블록에서 지역 변수가 되는 블록 레벨 스코프
var x = 42;
if (true) {
var x = 10;
let y = 20;
const z = 30;
}
console.log(x); // 10
console.log(y); // ReferenceError: y is not defined
console.log(z); // ReferenceError: z is not defined
✅ 스코프 체인 (Scope Chain)
상위 스코프와 하위 스코프가 계층적으로 연결된 것
- JS 엔진은 상위 스코프 방향으로만 이동하며 변수를 검색하기 때문에 하위 스코프에 있는 변수를 상위 스코프에서 참조할 수 없다.
✅ 렉시컬 스코프 (lexical scope)
let x = 1;
function superShy() {
let x = 10;
howSweet();
}
function howSweet() {
console.log(x);
}
superShy(); // ?
howSweet(); // ?
1️⃣동적 스코프(Dynamic Scope)
호출된 위치로 상위 스코프 결정
- superShy() 내부에서 호출되었으므로 howSweet()이 하위 스코프가 되고 superShy() 내에서 x를 검색하여 10 출력
- 코드 작성 순으로 코드가 실행되는 것이 아니므로 가독성이 떨어진다.
2️⃣정적 스코프(Static Scope)
선언된 위치로 상위 스코프 결정
- a.k.a 렉시컬 스코프
- superShy() 내부에서 호출되었지만 선언 위치가 전역 스코프이기 때문에 전역에서 x를 검색하여 1출력
- JS가 상위 스코프를 결정하고 코드를 실행하는 방식
✅ 클로저(Closure)
자신이 생성될 때의 환경(Lexical Environment)을 기억하는 함수
- 반환된 내부함수가 자신이 선언되었을 때의 환경(스코프)을 기억하여 스코프 밖에서 호출되어도 해당 스코프에 접근할 수 있는 함수
- 스코프를 이용하여 변수의 접근 범위를 close 한다.
- 외부함수 ➡️ 내부함수 접근 불가
- 내부함수 ➡️ 외부함수 접근 가능
function outer() {
var x = 10;
var inner = function() { console.log(x); };
return inner;
}
var newInner = outer();
newInner(); // 10
- 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우 외부함수 밖에서 외부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있다.
💡A closure is the combination of a function and the lexical environment within which that function was declared.
-MDN
- function: 리턴된 inner
- lexical environment: inner가 선언되었을 때의 스코프
📍실행 컨텍스트의 관점
- 내부함수가 유효한 상태에서 외부함수가 종료하여 외부함수의 실행 컨텍스트가 반환되어도, 외부함수 실행 컨텍스트 내의 활성 객체(변수, 함수 선언 등의 정보를 가지고 있는 객체)는 내부함수가 참조하는 한 유효하여 내부함수가 스코프 체인을 통해 참조할 수 있다.
- 즉, 외부함수 내의 변수는 이를 필요로 하는 내부함수가 하나 이상 존재하는 경우 계속 유지된다.
✅ 클로저의 활용
1️⃣ 상태 유지 및 전역 변수 사용 최소화
현재 상태를 기억하고 변경된 최신 상태를 유지하는 데 사용
- 클로저에 의해 참조되고 있는 변수는 유효하며 자신의 변경된 최신 상태를 유지한다.
- 전역 변수는 언제든지 누구나 변경할 수 있기 때문에 사용에 신중해야하는데, 클로저를 사용하면 변수의 의도치 않은 상태 변경을 방지할 수 있으며 변수의 변경 상태를 기억할 수 있다.
- 불변성을 지향하는 함수형 프로그래밍에서 Side Effect를 최대한 억제하여 오류를 피하고 프로그램의 안전성을 높일 수 있다.
2️⃣ 데이터 보존
자유 변수 (Free Variable)에 접근 가능
- 외부 함수의 실행이 끝나더라도 외부 함수 내의 자유 변수를 사용할 수 있다.
- 특정 데이터를 스코프 안에서 계속 사용하고 보존할 수 있다.
3️⃣ 모듈화를 통한 코드 재사용
변수의 값을 독립적으로 관리 가능
- 각각의 변수에 클로저 함수를 할당하면 각각 독립적으로 값을 관리할 수 있다.
- 데이터와 메소드를 모듈화하고 함수의 재사용성을 극대화할 수 있다.
4️⃣ 클로저 모듈 패턴으로 캡슐화
클로저 모듈 패턴을 통해 정보 접근 제한 가능
- 자유 변수는 클로저로 인해 외부에서 접근할 수 없고 메서드를 통해서만 접근할 수 있다.
- JS에는 private 등의 접근 제한자가 없기 때문에 클로저 모듈 패턴을 활용하여 정보 접근을 제한한다.
✨ Appendix
✅ 렉시컬 환경 (lexical environment)
코드가 어디에서 실행되며 주변에 어떤 코드가 있는지
- 실행할 스코프 범위 안에 있는 변수와 함수를 프로퍼티로 저장하는 객체
- 코드의 문맥, 즉 컨텍스트는 렉시컬 환경으로 이루어지는데 이를 구현한 것이 실행 컨텍스트이다.
- 모든 코드는 실행 컨텍스트에서 평가되고 실행된다.
✅실행 컨텍스트
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
- 변수 객체, 스코프 체인, this 정보가 담겨 있다.
- 자동으로 전역 컨텍스트가 생성되고 호출할 때마다 함수 컨텍스트가 생성된다.
- 실행 중인 함수 내의 변수 상태를 렉시컬 환경에 저장해두고 변경이 있을 때마다 업데이트 하고 스코프 체인에 따라 탐색하여 사용한다.
- 함수 실행이 끝나면 함수 컨텍스트가 사라지고, 페이지를 종료하면 전역 컨텍스트도 사라진다.
✨ 참고할 만한 글
https://developer.mozilla.org/ko/docs/Glossary/Scope
스코프 - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN
스코프는 컨텍스트는 값과 "표현식"이 "표현"되거나 참조 될 수 있는 현재 실행되는 컨텍스트를 의미합니다. 만약 변수 또는 표현식이 "해당 스코프"내에 있지 않다면, 사용할 수 없습니다. 스코
developer.mozilla.org
https://poiemaweb.com/js-closure
Closure | PoiemaWeb
클로저(closure)는 자바스크립트에서 중요한 개념 중 하나로 자바스크립트에 관심을 가지고 있다면 한번쯤은 들어보았을 내용이다. execution context에 대한 사전 지식이 있으면 이해하기 어렵지 않
poiemaweb.com
http://dmitrysoshnikov.com/ecmascript/chapter-6-closures/
ECMA-262-3 in detail. Chapter 6. Closures.
Read this article in: Russian, French. IntroductionGeneral theoryDefinitionsFunarg problemClosureECMAScript closures implementationOne [[Scope]] value for “them all”Funarg and returnTheory versionsPractical usage of closuresConclusionAdditional literat
dmitrysoshnikov.com
https://billyboo.tistory.com/24
[JS] 모던 자바스크립트 Deep Dive - 13. 스코프
스코프 (Scope)식별자가 유효한 범위. 유효 범위라고도 한다. 식별자를 검색하는 규칙모든 식별자 (변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신
billyboo.tistory.com
https://billyboo.tistory.com/36
[JS] 모던 자바스크립트 Deep Dive - 24. 클로저
클로저함수와 그 함수가 선언된 렉시컬 환경과의 조합 - MDN에서의 정의함수가 선언된 렉시컬 환경렉시컬 스코프자바스크립트 엔진은 함수를 어디에서 호출했는지가 아니라 함수를 어디에 정의
billyboo.tistory.com