4-3 콜백 함수는 함수다

만약 콜백 함수로 어떤 객체의 메서드를 넘겨준다 하더라도 이 메서드는 메서드가 아닌 함수로서 호출된다.

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를 가리키게 된다.

4-4 콜백 함수 내부의 this에 다른 값 바인딩하기

객체의 메서드를 콜백 함수로 전달하면 콜백 함수 내부의 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

클로저가 어디에 쓰였나