클로저 closure

브리셀·2021년 8월 2일
0

JavaScript

목록 보기
2/8
post-custom-banner

클로저란

예시1

function makeFunc() {
  var name = "Mozilla";
  function displayName() { //외부변수를 참조하는 내부함수, 클로저
    alert(name);
  }
  return displayName; 
}

var myFunc = makeFunc();
//myFunc변수에 displayName을 리턴함
//유효범위의 어휘적 환경을 유지
myFunc();
//리턴된 displayName 함수를 실행(name 변수에 접근)
  1. 지역변수 name이 생성된다.
  2. name을 참조하는 함수 displayName()이 생성된다.
  3. displayName()이 리턴되어 외부변수 myFunc에 할당된다. (클로저 생성)
  4. 위 환경이 그대로 저장되기 때문에, 나중에 myFunc()을 호출해도 name에 접근할 수 있다.

예시2

2-1 클로저가 아님

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(var index in arr) {
    console.log(arr[index]());
}
  1. 전역변수 i가 생성된다.
  2. arr의 요소마다 전역변수 i를 참조하는 function() { return i; }가 할당된다.
  3. 마지막에 arr를 요소마다 호출하면, 각 요소에 할당된 클로저는 전역변수 i를 참조하고 있으므로, for문에 의해 5까지 증가한 전역변수 i를 리턴하게 된다.

2-2

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(id) {
        return function(){
            return id;
        }
    }(i);
}
for(var index in arr) {
    console.log(arr[index]());
}
  1. 전역변수 i가 생성된다.
  2. arr의 요소마다 지역변수 id=i를 참조하는 function() { return id; }가 할당된다.
  3. 마지막에 arr를 요소마다 호출하면, 각 요소에 할당된 클로저는 서로 다른 동명의 지역변수 id를 참조하고 있으므로, 각각의 값을 리턴하게 된다.

2-3 var 대신 let을 쓰면

let arr = []
for(let i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(let index in arr) {
    console.log(arr[index]());
}
  1. let변수(?) i가 생성된다.
  2. arr의 요소마다 let변수 i를 참조하는 function() { return i; }가 할당된다.
    • 이 때 let변수 i는 {} 내에서만 유효하므로(=반복문이 한 차례 끝나면 효력을 잃으므로) 나중에 호출해도 var i처럼 전역변수를 리턴하지는 않게 된다.
  3. 마지막에 arr를 요소마다 호출하면, 각 요소에 할당된 클로저는 각 순간의 let변수 i를 참조하고 있으므로, 각각의 값을 리턴하게 된다.

그럼 let을 쓰면 되지, 왜 이런 어려운 걸 쓰나요?

var 밖에 없을 당시에 만들어진 코드가 있고
var 밖에 쓸 수 없는 환경도 있기 때문이다. (...)

참고한곳

profile
풀스택도 프론트부터
post-custom-banner

0개의 댓글