Table of Contents
this
- 객체에서 동작을 나타내는 메서드는 자신의 상태를 참조하고 변경할 수 있어야 한다. 이 때 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면 먼저 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다
- 자바스크립트는 자신이 생성할 인스턴스를 가리키는 this라는 특수한 식별자를 제공한다
- this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다
-
단 자바스크립트에서 this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다
- 동일한 함수도 다양한 방식으로 호출할 수 있다. 함수를 호출하는 방식은 다음과 같다
- 일반 함수 호출
- 메서드 호출
- 생성자 함수 호출
Function.prototype.apply/call/bind
메서드에 의한 간접 호출
일반 함수 호출
- 일반함수로 호출된 모든 함수(중첩함수, 콜백 함수 포함) 내부의
this
에는 전역 객체가 바인딩된다 - 하지만 메서드 내에서 정의한 중첩 함수 또는 메서드에게 전달한 콜백 함수가 일반 함수로 호출될 때
this
가 전역 객체를 바인딩하는 것은 문제가 있다 - 이 문제를 해결하는 가장 깔끔한 방법은 화살표 함수를 사용하는 것이다
- 화살표 함수 내부의
this
는 상위 스코프의 this를 가리킨다
const obj = {
value: 100,
foo() {
setTimeout(() => console.log(this.value), 100)
}
}
메서드 호출
- 메서드 내부의
this
는 메서드를 호출한 객체가 바인딩 된다
생성자 함수 호출
- 생성자 함수 내부의
this
에는 생성자 함수가 미래에 생성할 인스턴스가 바인딩 된다
Function.prototype.apply/call/bind 메서드에 의한 간접 호출
apply
,call
,bind
메서드는Function.prototype
의 메서드다. 즉 이들 메서드는 모든 함수가 상속받아 사용할 수 있다apply
와call
메서드는 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩한다- (
apply
는 전달할 인수를 배열 형식으로 전달,call
은 쉼표로 구분하여 전달하는 차이다) bind
메서드는 함수를 호출하지 않는다bind
메서드는 첫 번째 인수로 전달한 객체에 바인딩된 새로 생성된 함수를 반환한다- 위에서 일반 함수의
this
가 전역 객체에 바인딩되는 문제를 화살표 함수로 해결했었는데, 이 문제를apply/call/bind
로 해결할 수도 있었다 - 콜백함수 안에 사용된 함수가 일반 함수로 정의된 함수가 전달될 수 있기 때문에
bind
메서드를 사용해 이 문제를 사전에 방지할 수 있다
const person = {
name: 'Lee',
foo(callback) {
setTimeout(callback.bind(this), 100)
}
}
// 이렇게 일반 함수가 전달되어도 사전에 bind 메서드를 사용해서 문제를 사전에 방지했기 때문에 괜찮다
person.foo(function() { console.log(`Hi my name is ${this.name}`) })
결론
- 메서드나 생성자 함수는 크게 걱정할 문제가 없다
- 만약 콜백함수로 사용될 가능성이 있는 함수는 일반 함수로 정의하는 것보다는, 화살표 함수로 정의하는게 낫다
- 콜백함수가 일반함수로 정의되었다면, 콜백함수를 참조하는 곳에서
bind
메서드를 사용해 바인딩 해야 한다