만약 콜백 함수로 어떤 객체의 메서드를 넘겨준다 하더라도 이 메서드는 메서드가 아닌 함수로서 호출된다.
var obj = {
vals: [1, 2, 3],
logValues: function(v, i) {
console.log(this, v, i)
}
}
obj.logValues(1, 2) // (1) - obj 1 2
[4, 5, 6].forEach(obj.logValues)
// (2)
// Window 4 0
// Window 5 1
// Window 6 2
(1)의 경우 logValues()는 메서드로서 호출되었다. 따라서 this가 obj를 가리키게 된다.
(2)의 경우 forEach()의 콜백 함수로 넘겨준 함수는 obj.logValues 메서드 자체가 아닌, obj.logValues가 가리키는 함수 function(v, i) { … }
이다. forEach() 안에서 이 함수가 메서드로서가 아닌 함수 자체로서 호출되었으므로, 이 함수 내부의 this는 전역 객체를 가리킨다.
이는 실제로 다음과 같이 코드를 작성했을 때 this의 값으로 Window가 아닌 obj가 나오는 것을 보고 알 수 있다.
[4, 5, 6].forEach((v, i) => obj.logValues(v, i))
// (2)
// obj 4 0
// obj 5 1
// obj 6 2
이 때는 obj의 메서드로서 호출되었기 때문에 내부에서의 this가 obj를 가리키게 된다.
객체의 메서드를 콜백 함수로 전달하면 콜백 함수 내부의 this가 해당 객체를 바라보지 않는다 했다. 하지만 의도적으로 객체를 바라볼수록 할 수 있는 방법이 없을까?
전통적으로는 this를 다른 변수에 담아 콜백 함수 내에서 this 대신 해당 변수를 사용하게 하고 이를 클로저로 만들도록 하였다.
var obj1 = {
name: 'obj1',
func: function () {
var self = this
return function () {
console.log(self.name)
}
}
}
var callback = obj1.func()
setTimeout(callback, 1000) // obj1
클로저가 어디에 쓰였나