클로저가 잘 이해가 되지 않는 와중에 (특히나 이해가 안되기보단 와닿지 않았다) 어떤 의의를 가진 것인지 잘 나타내는 영상이 있어서 참고하였다. 영상
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
console.log(cnt); //0출력
cntPlus();
console.log(cnt); //1출력
cnt를 선언하고 cntPlus라는 함수를 작성했다.
그런데 코드를 이렇게 작성하고 작업하다보면 의도치 않게 다음과 같은 상황이 발생할 수 있다.
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
console.log(cnt);
cntPlus();
console.log(cnt);
//수많은 코드들로 작업함
cnt = 100; //의도치 않게 이름이 겹치게 선언해버림
cntPlus();
console.log(cnt); //101로 바뀌어버린다
cnt라는 변수를 cntPlus라는 함수를 통해 1씩만 증가되게 하고싶었는데 의도치 않게 cnt값을 직접 접근하여 바꾸는 일이 발생해버릴 수 있다.
그렇기에 우리는 cnt라는 변수에 직접 접근할 수 없도록 closure라는 개념을 활용한 코드를 짜야 하는 것이다.
우선 함수로 한번 감싸 지역변수로 만들어준다.
function closure() {
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
}
//console.log(cnt); 접근 불가
closure.cntPlus();
console.log(closure.cnt);
이렇게 실행하면 되지 않을까? 싶었지만
closure 내부에서 선언된 cnt와 cntPlus는 전역에서는 접근이 불가능하다.
따라서 cnt변수를 외부에서 접근할 수 있도록, return을 활용하여 외부 스코프에 이를 저장시켜야한다.
function closure() {
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
return {
cntPlus
};
}
let test = closure();
test.cntPlus();
이렇게 실행시 정상적으로 cnt는 1로 증가한다. 그런데 cnt를 console.log로 찍어서 확인하는것 역시 불가능한 상황이다.
여기서 똘똘한 사람은 '아 그럼 console.log도 closure내부의 다른 함수로 빼주고 리턴하면 되겠구나' 라고 생각할 수 있다.
function closure() {
let cnt = 0;
function cntShow() {
console.log(cnt);
}
function cntPlus() {
cnt = cnt + 1;
}
return {
cntPlus,
cntShow,
};
}
let test = closure();
test.cntShow(); //0
test.cntPlus();
test.cntShow(); //1
이렇게 하면 우리가 클로저를 통해
건드리고 싶지 않은 변수는 일반적으로 접근하여 값을 고칠 수 없게 만드는
은닉화 라는것을 실습할 수 있게 된다
추가)) JS활용 연습
방금 위의 코드를 익명함수를 활용해 변형시켜 볼 수도 있다.
function closure() {
let cnt = 0;
function cntPlus() {
cnt = cnt + 1;
}
return {
cntPPlus: cntPlus, //cntPPlus: cntPlus()로 수정하면 코드가 제대로 동작하지 않는다.
cntShow: function () {
//console.log(cnt);
return cnt;
},
};
}
let test = closure();
console.log(test.cntShow()); //0
test.cntPPlus();
console.log(test.cntShow()); //1
주석처리된 cntPPlus: cntPlus()로 수정하면 코드가 제대로 동작하지 않는다.
- cntPlus는 함수를 나타내는 참조(reference)를 저장하는 속성(property)이어야 한다. cntPlus()는 함수를 호출한 결과를 반환하는 것이므로 함수 자체를 저장하는 것이 아니라 함수를 호출한 결과를 저장하게 된다.
- 함수를 호출한 결과를 저장하면, 나중에 해당 함수를 실행하려 할 때 문제가 발생한다. 객체의 속성으로 저장된 함수를 실행하려면 ()를 사용해야 하는데, 이때 cntPPlus()가 아닌 cntPPlus로 접근해야 한다.
- 그렇다고 test.cntPPlus를 실행해버리면 실제로 cntPlus을 실행하는게 아니라 그저 참조하는 것일 뿐임. ['add(1,2)'를 실행하는 것처럼 실행은 'cntPPlus()'로 해야함
- 따라서 cntPPlus: cntPlus로 함수 자체를 속성으로 저장하고, 필요할 때 test.cntPPlus()로 함수를 실행해야한다.
'JS' 카테고리의 다른 글
[JS] 제너레이터 실습 - 모던자바스크립트 DeepDive (0) | 2023.10.12 |
---|---|
[JS] 프로미스 - 모던자바스크립트 DeepDive (1) | 2023.10.08 |
[JS] DOM이벤트로 익히는 호이스팅과 즉시실행함수 (1) | 2023.10.03 |
[JavaScript] 호이스팅, 스코프 (0) | 2023.09.10 |
[JavaScript] 실행 컨텍스트 (0) | 2023.09.10 |