whatisthis?

javaScript. 클로저(Closure) 본문

WEB STUDY/JAVASCRIPT

javaScript. 클로저(Closure)

thisisyjin 2022. 1. 11. 14:16

___

 

>> Lexical scoping에 대해 포스팅 한 글을 먼저 참고하자.

 

 

javaScript. 함수 스코프(scope)

자바스크립트에서 ECMAscript 5 이전에는 var로 선언한 변수로 데이터를 저장했었다. (ECMA5이후에는 const와 let이 등장하였다. 현재 var은 웬만해선 쓰지 X) var로 전역(global)변수를 만드는 것은 삼가야

mywebproject.tistory.com

___

 

 

클로저(Closure)

- 함수와 함수가 선언된 어휘적 환경의 조합

- 비공개 변수를 가질 수 있는 환경에 있는 함수

 

 

** 비공개 변수란?

클로저 함수 내부에 생성한 함수도 아니고, 매개변수도 아닌 변수.

 

var makeClosure = function() {
  var name = 'zero';
  return function () {
    console.log(name);
  }
};
var closure = makeClosure(); // function () { console.log(name); }
closure(); // 'zero';

위 예제에서  closure 함수 안에 console.log(name)이 있다. (makeClosure 함수의 코드가 그대로 존재)

name은 closure함수의 매개변수(parameter)도 아니고, closure 함수 내부에서 생성한 변수도 아니다.

-> name은 비공개변수이다.

 

function() { console.log(name) }은 name 변수나, name 변수가 있는 스코프에 대해 클로저라고 부를 수 있다.

>> 즉, 해당 함수에서 name을 생선한 것도 아니고 매개변수도 아니므로 (비공개변수를 가질 수 있는 환경)

 

 

** 컨텍스트 관점에서 살펴보자.

 

① 전역 컨텍스트 생성

"전역 컨텍스트": {
  변수객체: {
    arguments: null,
    variable: [{ makeClosure: Function }, 'closure'],    // maekeClosure은 함수표현식이므로
  },
  scopeChain: ['전역 변수객체'],
  this: window,
}

 

② makeClosure() -  makeClosure 컨텍스트 생성 (함수 호출시 생성되므로)

"makeClosure 컨텍스트": {
  변수객체: {
    arguments: null,
    variable: [{ name: 'zero' }],  // makeClosure 내에서 선언한 name변수
  },
  scopeChain: ['makeClosure 변수객체', '전역 변수객체'],    // 본인 + 상위
  this: window,
}

 

③ var closure = makeClosure(); 에 의해 

function을 return하는데  (🔻아래 부분)

return function () {
    console.log(name);
  }

스코프체인은 makeClosure과 전역 변수객체를 포함한다.

 

위 예제 🔻

더보기
var makeClosure = function() {
  var name = 'zero';
  return function () {
    console.log(name);
  }
};
var closure = makeClosure(); // function () { console.log(name); }
closure(); // 'zero';

따라서 closure을 호출할 때 (마지막줄 closure(); 부분) closure 컨텍스트는

"closure 컨텍스트":  {
  변수객체: {
    arguments: null,
    variable: null,
  scopeChain: ['closure 변수객체', 'makeClosure 변수객체', '전역 변수객체'],
  this: window,
}

스코프체인을 보면 자기자신(closure) + function을 return할때의 스코프체인에 의해 makeClosure+전역도 포함

하게 된다.

 

 

 


 

💡 왜 클로저를 사용하는지?

 

비공개 변수를 만들어 활용 가능.

- 사용자가 조작할 걱정이 없고, 프로그램 사용자는 공개된 메소드만 사용해야 함.

- 즉, 사용자를 '통제'하기 위한 기본적인 방법이 클로저이다.

 

 

💡 클로저의 단점

 

- 성능 문제, 메모리 문제 발생 가능

- 비공개 변수는 언제 메모리관리를 해야할 지 모름 -> 메모리 낭비

- Scope Chain을 거슬러 올라가기 때문에 속도가 느림.

 

 

※ 추가 ※

EventListener을 for문으로 연결시 오류가 나는 이유 

 

for (var i = 0; i < 5; i++) {
  $('#target' + i).on('click', function() {
    alert(i);
  });
}

 

lexical Scoping에 의해 함수는 선언할 때 스코프가 생성된다.

즉, 이벤트리스너 안의 i는 외부의 i를 계속 참조하는 것.

i는 반복문 종료 후 최종적으로 5가 되기 때문에 

결과는 계속 5가 나오게 됨.

 

>> 클로저를 만들어주면 해결됨

 

 

 


REFERENCE

https://www.zerocho.com/category/JavaScript/post/5741d96d094da4986bc950a0

 

(JavaScript) 실행 컨텍스트 - 클로저와 호이스팅

안녕하세요. 이번 시간에는 범위에 이어 실행 컨텍스트와 클로저에 대해서 살펴보겠습니다. 제가 지난 시간에 실행 컨텍스트가 제일 중요하다고 하면서 강좌를 마쳤습니다. lexical scoping과 이것

www.zerocho.com

이 포스팅은 zerocho님의 javascript 강의를 보고 작성한 글입니다.

공부+기록 용으로 작성한 것이며, 자세한 것은 위 포스팅을 참고하세요!