순서가 조금 잘못된 것 같긴한데, 어쩔 수 없다고 생각한다.
체계적으로 공부를 해서 기초부터 차근차근 닦아올려가며 일을 하게 된 것이 아니라
당장 오늘 이 코드를 작성하지 못하면 큰일난다는 생각으로 언제나 목에 칼이 들어온 기분으로
코드를 만들어가며 체득하는 신입 SI 개발자는 이런 체계적인 용어? 개념적인 지식? 그런거 모르기 때문에
아 내가 지금까지 써온 이런게 이런 이름이구나~ 라며 깨닫기 마련이다.
오늘은 이런 식으로 깨달은 Scope 와 Closure 기법에 대한 이야기를 해보고자 한다.
1. Scope (유효범위)
Scope는 유효범위를 의미한다.
정의나 설명을 통해 이야기하면 누구나 한번에 이해하긴 힘들다. 하지만 일단 이런거다 정도는 알고 있어야하니 정리해보자.
함수, 변수를 선언 했을 때 그 함수나 변수를 인지, 사용할 수 있는 범위 라고 생각하면 될 것 같다.
1) Scope의 분류
const global = () => {
const globalVar = '';
// 전역에서 선언하였으니 해당 변수는 이 global 함수 전역에서 사용가능한 전역 스코프를 가진다.
const localFunc = () => {
const localVar = '';
// localFunc 이라는 함수 내에서 선언한 이 변수는 이 함수내에서만 스코프를 가지고 사용할 수 있다.
console.log(localVar);
console.log(globalVar);
};
localFunc(); // local global 둘다 동일하게 정상적으로 출력
console.log(localVar); // undefined
console.log(globalVar); // '' 로 출력
};
Scope는 Global Scope, Local Scope 두가지로 나뉘어진다.
Global Scope는 스크립트 전역에서 어느 곳에서나 참조가 가능하다.
Local Scope는 정의된 함수 내에서만 참조가 가능하다. 해당 함수 외부에서는 참조가 불가능하게 된다.
2) Scope의 특징
(1) 함수 단위의 유효범위 (function-level-scope) => 함수 내에서 선언되면 함수 코드블록 내에서만 유효하다.
(위 코드블럭 참조)
(2) 변수명 중복 허용 => 전역에서 선언하면 어디서든 쓸 수 있는 Global Scope를 가진다.
(위 코드 블럭 참조)
(3) 암묵적 선언 => 명시적으로 변수 앞에 변수임을 의미하는 var를 선언하지 않으면 암묵적으로 전역이 된다.
const global = () => {
const localFunc = () => {
x = '';
}
console.log(x); // '' 출력
}
(4) Lexial Scoping (Static Scoping) => 함수가 선언된 시점에서 유효범위를 가진다.
const local = () => {
let count = 0
const localFunc = () => {
count += 1
};
return {
plus: localFunc(),
check: () => {console.log(count);}
}
}
const { plus, check } = local();
이 코드를 보면서 생각해보면 local 이라는 함수는 이미 실행되어 소멸되어있다.
하지만 plus는 count라는 local 내의 global 변수를 기억하고 해당 변수의 값에 +1을 해줄 것이다.
또한 check 역시도 count 라는 변수의 값을 출력해줄 것이다.
즉, 해당 함수가 선언되어있던 상위 함수가 이미 실행되어 소멸한 상태라도 선언 시점의 Scope를 기억하고 있기 때문에
이 코드가 유효하게 실행될 수 있는 것이다.
3) Scope Chain
사실 앞선 모든 설명은 이 Scope Chain을 설명하기 위해서 또, 이 Scope Chain을 설명할 수 있어야 Closure를 설명할 수 있으니 한거라고 볼 수 있다.
Scope Chain은 각 함수마다 가지고 있는 Scope를 연결하는 모습을 보여주는 것이라고 생각하면 된다.
React에서 Custom Hook을 만들어 본 사람이라면 Hook의 형태를 생각해보면 이해하기 좋을 것 같다.
말로 설명하면 정말 와닿지 않으니 이건 코드를 통해 들여다보는게 좋을 것 같다.
const local = () => {
let count = 0
const localFunc = () => {
count += 1
};
return {
plus: localFunc(),
check: () => {console.log(count);}
}
}
const { plus, check } = local();
위 의 코드 블럭을 한번 더 가져왔다. 사실 Hook이라면 앞에 use를 붙여주는 것이 규칙이지만
설명을 위해 한번 더 사용하는 것이니 이해해주길 바란다.
이 코드를 보면 Scope Chain을 이해할 수 있다.
localFunc은 상위 함수인 local의 global 변수를 기억하고 있고, 이를 통해 실행이 가능하다.
만일 local 함수역시 상위 함수에 포함 되어있고 해당 함수의 변수를 사용하고 있다면 또 상위 함수의 변수를 기억하게 될 것이다.
이렇게 이어져 나가는 것을 Scope Chain 으로 이해하면 될 것 같다.
2. Closure
이미 앞에서 다 설명해버렸긴 한데 다시 정리해서 설명해보겠다.
Closure 기법은 Scope Chain 개념, Lexial Scoping 이라는 특징을 통해 각 함수가 자신을 선언 했을 때의 Scope를 기억한다는 점을 이용한 기법이라고 생각하면 된다. 즉, 앞에서 코드 블럭에 작성한 코드들이 이 Closure를 사용한 코드들이라고 보면 된다.
함수는 실행되면 자연히 소멸한다. 헌데 앞선 이 특징들을 활용하면 특정 함수를 실행할 때 이미 소멸해버린 상위 함수 내에서 선언된 변수를 기억하고 사용할 수 있게 된다. 이것이 Closure 기법이다.
'Dev > JavaScript' 카테고리의 다른 글
[원리] 실수 표현 원리 (0) | 2023.05.30 |
---|---|
[JavaScript] parseInt() (0) | 2023.05.23 |
[JavaScript] Hoisting (0) | 2023.04.20 |
[JS].sort() (1) | 2023.04.14 |
JavaScript를 시작하기 전에 (1) (0) | 2023.04.10 |