어떤 상황에서 클로저를 사용할 수 있는지 알아보도록 하자.
콜백 함수 내부에서 외부의 데이터를 사용하기 위해 클로저를 사용할 수 있다.
이벤트 리스너에 대한 한 예제를 보자.
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()에 콜백 함수로 들어가는 함수들이다. 이 둘을 비교하면서 봐 보자.
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 함수를 사용하여 고칠 수 있다.