자바스크립트의 this는 기본적으로 전역객체를 가르킨다. 그래서 콜백 함수에서 원하는 처리 못하는 것을 경험한 적이 있을 것이다. 화살표 함수를 활용하는 것도 방법이겠지만, class의 메소드 같은 경우는 그럴 수 없기 때문에, call, apply, bind 메소드를 활용해야 한다.
call, apply, bind 메소드는 Function.prototype의 메소드로 모든 함수에서 호출할 수 있다. 이들은 this로 사용할 객체와 인수들을 입력받아 실행시킨다. 이들간의 차이점은 다음과 같다.
/**
* Calls a method of an object, substituting another object for the current object.
* @param thisArg The object to be used as the current object.
* @param argArray A list of arguments to be passed to the method.
*/
call(this: Function, thisArg: any, ...argArray: any[]): any;
어떤 객체의 메소드를 호출시키는데(함수를 호출시키는데), 어떤 객체를 입력시킨 객체로 대체하고, 나머지 인자들을 인자로 넣어준다.
/**
* Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.
* @param thisArg The object to be used as the this object.
* @param argArray A set of arguments to be passed to the function.
*/
apply(this: Function, thisArg: any, argArray?: any): any;
apply는 함수를 호출시키는데, 입력받은 객체로 this를 대체하며 배열로 받은 인자를 넣어서 실행시킨다.
/**
* For a given function, creates a bound function that has the same body as the original function.
* The this object of the bound function is associated with the specified object, and has the specified initial parameters.
* @param thisArg An object to which the this keyword can refer inside the new function.
* @param argArray A list of arguments to be passed to the new function.
*/
bind(this: Function, thisArg: any, ...argArray: any[]): any;
실행시킨 함수에대해서, bound 함수를 생성한다. 이 바운드 함수는 입력받은 객체와 인자 배열로 연결된다.
apply, call은 함수를 실행시키고, bind는 실행은 되지 않는다.
apply, bind는 배열로 인자를 넣어주고, call은 여러 인자를 그냥 넣어준다.
apply는 함수를, call은 어떤 객체의 메소드를 실행시킨다고 명세되어 있는게 신기했다.
bind는 새 함수를 반환한다. 두 개의 handler.bind(this)는 다른 함수라는 의미다. 이벤트리스터를 해제시킬 때, handler.bind(this)를 둘다 해준다면 이는 다른 함수라 제거가 안됬는데 해답을 알게 되었다.
document.addEventListner('click',handler.bind(this))
document.removeEventListner('click',handler.bind(this)) // 지워지지 않음, 두 핸들러가 다른 식별자를 가리킴
bindedHandler = handler.bind(this)
document.addEventListner('click',bindedHandler)
document.removeEventListner('click',bindedHandler) // 지워짐
toString.call([1,2,3]); //"[object Array]"
toString.call(new Date); //"[object Date]"