어떤 상황에서 클로저를 사용할 수 있는지 알아보도록 하자.

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

콜백 함수 내부에서 외부의 데이터를 사용하기 위해 클로저를 사용할 수 있다.

콜백 함수 내부에서 외부 변수를 참조하기 1 - 콜백 함수를 내부함수로 선언해서 직접 참조

이벤트 리스너에 대한 한 예제를 보자.

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

fruits.forEach(function (fruit) {              // (A)
  var $li = document.createElement('li')
  $li.innerText = fruit
  $li.addEventListener('click', function () {  // (B)
    alert('your choice is ' + fruit)
  })
  $ul.appendChild($li)
})

document.body.appendChild($ul)

A 함수와 B 함수는 각각 forEach()와 addEventListener()에 콜백 함수로 들어가는 함수들이다. 이 둘을 비교하면서 봐 보자.

콜백 함수 내부에서 외부 변수를 참조하기 1.5 - 외부 함수 분리

B 함수의 재사용성을 높이기 위해 다음과 같이 외부 함수로 분리해 보자. 이 때 외부의 변수를 인자로 받는다.

var fruits = ['apple', 'banana', 'peach']
var $ul = document.createElement('ul')

var alertFruit = function (fruit) {  // 외부 함수!
  alert('your choice is ' + fruit)
}

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

document.body.appendChild($ul)
alertFruit(fruits[1])

그런데 위의 코드에서 li 요소를 클릭하였을 때 나타나는 alert 창의 메세지가 좀 이상하다.

your choice is [object PointerEvent]

이는 addEventListner의 콜백의 첫번째 인자로는 늘 이벤트 객체가 들어가기 때문이다. 이는 bind 함수를 사용하여 고칠 수 있다.