일급 객체를 공부하다 보니
렉시컬 스코프, 클로저에 대한 궁금증이 생겨 이에 대해 공부한 기록이다.
Lexical Scope
렉시컬 스코프는 말 그대로 어휘의 범위이다.
변수가 사용 가능한 범위를 알기 위해 어디에서 선언되었는지 고려하는 것을 의미한다.
JS는 선언자에 따라 다른 렉시컬 스코프를 가진다.
var
전통적인 JS에는 함수 스코프와 전역 스코프 두 가지만 존재했다.
var 선언자는 선언된 위치에 따라 다른 스코프를 가진다.
- 함수 내부 : 함수 스코프
- 함수 외부 : 전역 스코프
함수 외부에서 전역 스코프를 가지기 때문에
아래와 같은 문제가 발생할 수 있다.
if (Math.random() > 0.5) {
var x = 1;
} else {
var x = 2;
}
console.log(x);
x는 Math.random() 값에 따라 반환되어야 하는 값이다.
하지만 var 선언자에 의해 전역적으로 생성됨에 따라
마지막에 선언된 x의 값인 2가 콘솔에 찍히게 된다.
JS는 블록 스코프 변수를 생성할 수 있도록 let과 const를 이용할 수 있다.
let, const
let과 const는 블록 스코프 변수를 생성할 수 있다는 공통점을 가진다.
let은 변경이 가능한 변수, const는 변경이 불가능한 변수를 생성한다.
if (Math.random() > 0.5) {
const x = 1;
} else {
const x = 2;
}
console.log(x); // ReferenceError: x is not defined
var 변수를 사용했을 때 일어났던 문제가 해결되었다.
const 선언자를 이용해 x를 블록 스코프 변수로 생성함에 따라
Math.random() 값에 의해 x 값이 결정되게 하였다.
이번 기록에서 다룰 클로저는 모든 스코프의 변수를 캡처할 수 있다.
Closure
클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다.
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
먼저 myFunc 변수는 makeFunc() 함수가 실행됨에 따라
생성되는 displayName 함수의 인스턴스에 대한 참조다.
displayName 함수의 인스턴스는 변수 name이 있는 어휘적 환경에 대한 참조를 유지한다.
요약하면 현재 코드에서 myFunc는 함수 외부에 위치하기 때문에
name 변수를 참조할 수 없다.
하지만, displayName이 어휘적 환경에 대한 참조를 유지하기 때문에
name 변수를 사용할 수 있는 것이다.
정보의 은닉화
클로저를 이용해 정보의 은닉화를 구현할 수 있다.
간단한 카운터를 구현해 보자.
함수 외부에서는 카운터의 값이 몇인지 참조할 수 없게 하고 싶다고 가정하자.
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
privateCounter 변수는 counter 함수 내부에서 선언된 변수이므로,
함수 스코프를 가지기 때문에 외부에서 접근할 수 없는 변수이다.
오직 privateCounter변수에 대한 참조를 가지고 있는
increment, decrement, value 함수를 통해서만 외부에서 privateCounter 변수에 접근할 수 있다.
이처럼 클로저를 통해 private과 같은 기능을 구현할 수 있다.
참고
마치며
기본적인 개념들을 다루다 보니 모르는 개념이 꼬리를 물고 계속해서 생긴다.
하나씩 천천히 다루며 기록할 계획이다.
잘못된 정보에 대한 피드백은 환영입니다.
감사합니다.
'Frontend > JS' 카테고리의 다른 글
[JS] Javascript 일급 객체(First Class Object, First Class Function) (0) | 2023.01.05 |
---|---|
[JS] 로컬스토리 사용법(Set, Get, Remove, JSON) (0) | 2022.07.20 |
[JS] 자바스크립트에 CSS 적용하기/classList/toggle (0) | 2022.07.08 |