[JS] Closure

Let's TECH🧐·2020년 3월 7일
0

위 블로그는 생활코딩 사이트에서 클로저에 대한 강의를 듣고 스스로 이해한 뒤, 해당 사이트를 상당 부분 참고하여 작성한 내용이다.

정의

클로저(closure)는 내부함수가 외부함수의 맥락에 접근할 수 있는 것을 가리킨다.

예제1

function outter() {
  let title = 'Hello World!';
  function inner() {
    console.log(title);
  }
  inner();
}
outter(); // 'Hello World!'

이 예제는 내부함수 inner에서 title을 호출했을 때, 외부함수 outter의 지역변수인 title에 접근할 수 있음을 보여준다.

예제2

function outter() {
  let title = 'Hello World!';
  return function() {
	console.log(title);
  }
}

inner = outter();
inner(); // 'Hello World!'

위 예제의 마지막 두 행을 보자.
함수 outter를 호출함으로써 변수 inner에 function() { console.log(title) } 이 담겼다.
그런 후, 함수 inner를 다시 호출함으로써 'Hello World!'가 출력됨을 확인할 수 있다.

원래대로 라면 inner = outter() 라는 코드에서 outter 함수는 실행이 끝났기 때문에 해당 함수의 지역변수는 소멸해야 한다. 하지만, inner() 를 실행했을 때 'Hello World!'가 출력되는 것으로 보아 함수 outter의 지역변수 title이 소멸하지 않았다는 것을 알 수 있다.

이를 통해 우리는 클로저가 하는 역할에 대해 다시 생각해볼 수 있다.
클로저는 내부함수가 외부함수의 지역변수에 접근할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸할 때까지 소멸하지 않는 특성을 의미한다.

다음으로는, 클로저를 통해 사용할 수 있는 private한 속성에 대해 알아보겠다.

예제3

function myFavoriteFood(name) {
  return {
    get_name : function() {
	  return name;
    },
    set_name : function(_name) {
      name = _name; 
    }
  }
}

pizza = myFavoriteFood('pizza');
soup = myFavoriteFood('soup');

console.log(pizza.get_name()); // 'pizza'
console.log(soup.get_name()); // 'soup'

pizza.set_name('피자');

console.log(pizza.get_name()); // '피자'
console.log(soup.get_name()); // 'soup'

위 예제를 통해 알 수 있는 것들은 다음과 같다.

  1. 클로저는 객체의 메소드에서도 사용할 수 있다.
    위 예제를 보면 함수 myFavoriteFood의 리턴값으로 객체를 반환하고 있다. 이 객체는 메소드 get_name과 set_name을 가지고 있다. 해당 메소드들은 외부함수인 myFavoriteFood의 인자값으로 전달된 지역변수 name을 사용하고 있다. 이를 통해 객체의 메소드 또한 외부함수의 지역변수에 접근할 수 있다는 것을 알 수 있다.

  2. 동일한 외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다.
    pizza.set_name('피자')는 지역변수 name의 값을 '피자'로 변경했다. console.log(pizza.get_name())의 값이 '피자'인 것은 get_name과 set_name 메소드가 외부함수의 지역변수인 name의 값을 공유하고 있다는 의미이다.

  3. 똑같은 외부함수 myFavoriteFood를 공유하고 있는 pizza와 soup의 get_name의 결과는 각각 다르다.
    그 이유는 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 pizza와 soup은 각각 완전히 독립된 객체가 된다.

  4. myFavoriteFood의 지역변수 name은 두 번째 행에서 정의된 객체의 메소드에서만 접근할 수 있는 값이다. 이 말은 name의 값을 읽고 수정할 수 있는 것은 myFavoriteFood 메소드를 통해서 만들어진 객체 뿐이라는 의미다.
    JavaScript는 기본적으로 private한 속성을 지원하지 않는데, 클로저의 이러한 특성을 이용하여 private한 속성을 사용할 수 있다.

참고: Private 속성은 객체의 외부에서는 접근할 수 없는 외부에 감춰진 속성이나 메소드를 의미한다. 이를 통해서 객체의 내부에서만 사용해야 하는 값이 노출됨으로써 생길 수 있는 오류를 줄일 수 있다.

참고 사이트

profile
Minju's Tech Blog

0개의 댓글