코딩쌀롱

[코어 자바스크립트] 5-3 클로저의 활용 사례(외부 데이터 사용, 접근 권한 제어) 본문

[코어 자바스크립트] 5-3 클로저의 활용 사례(외부 데이터 사용, 접근 권한 제어)

이브✱ 2020. 12. 28. 18:05

콜백 함수 내부에서 외부 데이터를 사용하고자 할 때

1) 콜백함수를 내부함수로 선언, 외부 변수 직접 참조

const fruits = ['apple', 'banana', 'peach'];
const $ul = document.createElement('ul');      // (공통 코드)

fruits.forEach(function (fruit) {              // (A) forEach 콜백
   const $li = document.createElement('li');
   $li.innerText = fruit;
   
   $li.addEventListener('click', function() {  // (B) 클릭e 핸들러
      alert('your choice is ' + fruit);        // fruit 외부 변수 참조
   });
   
   $ul.appendChild($li);
});

document.body.appendChild($ul);

(A)는 fruits의 개수만큼 실행, 그때마다 새로운 실행 컨텍스트 활성화

(B)는 (A)의 실행 종료 여부와 무관하게 클릭 이벤트에 의해 실행됨. outerEnvironmentReference가 (A)의 L.E를 참조. 따라서 (B)함수가 참조할 예정인 변수 fruit에 대해서는 (A)가 종료된 후에도 GC대상에서 제외되고, 계속 참조 가능

 

 

2) bind 활용 - 인자 전달

(B) 함수를 외부로 분리해보았다. (B 함수가 다른 곳에서도 쓰일 경우 반복을 줄이기 위해)

const alertFruit = function (fruit) {
   alert('your choice is ' + fruit);
}

fruits.forEach(function (fruit) {
   const $li = document.createElement('li');
   $li.innerText = fruit;
   $li.addEventListener('click', alertFruit.bind(null, fruit));
   $ul.appendChlid($li);
});

document.body.appendChild($ul);

addEventListener는 콜백 함수를 호출할 때 첫 번째 인자에 '이벤트 객체'를 주입하기 때문에 bind메서드로 인자를 전달했다. 다만 이렇게 하면 이벤트 객체가 인자로 넘어오는 순서가 바뀌고, 함수 내부에서의 this가 원래와 달라지게 된다. 이런 변경사항이 발생하지 않게 하려면 bind 메서드가 아닌 다른 방식으로 풀어야한다. 

 

 

3) 고차함수 활용 - 클로저 적극 활용

const alertFruitBuilder = function (fruit) { // 외부 함수
   return function () {   // 내부 함수
      alert('your choice is ' + fruit);  // 외부 변수 참조
   };
};

fruits.forEach(function (fruit) {
   const $li = document.createElement('li');
   $li.innerText = fruit;
   $li.addEventListener('click', alertFruitBuilder(fruit));
   $ul.appendChild($li);
});

alertFruitBuilder라는 함수 내부에서는 다시 익명함수를 반환하는데, 이 익명함수가 바로 기존의 alertFruit함수다.

1. 이벤트 핸들러에서 alertFruitBuilder 함수를 실행하면서 fruit 값을 인자로 전달한다.

2. fruit을 참조하는 익명함수를 반환해서 콜백함수로써 전달한다.

 

 이후에 클릭 이벤트가 발생하면 이 함수의 실행 컨텍스트가 열리면서 alertFruitBuilder의 인자로 넘어온 fruit를 outerEnvironmentReference에 의해 참조할 수 있게 된다.  즉, alertFruitBuilder의 실행 결과로 반환된 함수에는 클로저가 존재한다.

 

접근 권한 제어(정보 은닉)

 정보 은닉(information hiding)은 어떤 모듈의 내부 로직에 대해 외부로의 노출을 최소화해서 모듈간의 결합도를 낮추고 유연성을 높이고자 하는 현대 프로그래밍 언어의 중요한 개념이다. 접근 권한에는 public, private, protected의 세 종류가 있다.

 - public : 외부에서 접근 가능

 - private : 내부에서만 사용, 외부에 노출X

 

클로저를 이용하면 함수 차원에서 public한 값과 private한 값을 구분하는 것이 가능하다.

const outer = function () {
   let a = 1;
   const inner = function () {
      return ++a;
   };
   return inner;
};

const outer2 = outer(); // == inner
console.log(outer2());
console.log(outer2());

 

outer 함수는 외부(전역 스코프)로부터 철저하게 격리된 닫힌 공간이다. 외부에서는 outer 함수를 실행할 수 있지만, outer 함수 내부에는 어떠한 개입도 할 수 없다. 외부에서는 오직 outer 함수가 return한 정보에만 접근할 수 있다. return 값이 외부에 정보를 제공하는 유일한 수단인 것이다. 

 

외부에 제공하고자 하는 정보들을 모아서 return하고, 내부에서만 사용할 정보들은 return하지 않는 것으로 접근 권한 제어가 가능한 것이다. return한 변수들은 public member, 그렇지 않으면 private member가 되는 것.

 

클로저를 활용해 접근권한을 제어하는 방법은 다음과 같다.

1. 함수에서 지역변수 및 내부함수 등을 생성한다.

2. 외부에 접근권한을 주고자 하는 대상들로 구성된 참조형 데이터(대상이 여럿일 때는 객체나 배열, 하나일 때는 함수)를 return한다. 

 

 

 


정재남 작가님의〔 코어 자바스크립트 〕책을 공부하며 정리했습니다.

 

Comments