자신이 속한 객체
또는 자신이 생성할 인스턴스
를 가리키는 자기 참조 변수이다.this 바인딩은 동적으로 결정됨
🔶🔸 [객체 리터럴의 메서드 내부에서 this] 🔸🔶
const circle = {
radius: 5,
getDiameter(){
return 2 * this.radius
}
}
circle.getDiameter() //10
🔶🔸 [생성자 함수 내부의 this] 🔸🔶
this는 생성자 함수가 생성할 인스턴스를 가리킨다.
function Circle(radius){
this.radius = radius
}
Circle.prototype.getDiameter = function(){
return 2 * this.radius
}
const circle = new Circle(6)
console.log(circle.getDiameter())
일반 함수 호출
메서드 호출
생성자 함수 호출
function.prototype.apply/call/bind 메서드에 의한 간접 호출
함수 호출 방식 | this가 가리키는 값 (this 바인딩) |
---|---|
일반 함수로서 호출 | 전역객체 |
메서드로서 호출 | 메서드를 호출한 객체(마침표 앞의 객체) |
생성자 함수로 호출 | 생성자 함수가 미래에 생성할 인스턴스 |
apply/call/bind | 함수 내부의this는 인수에 의해서 결정된다. |
기본적으로 this는 전역 객체가 바인딩된다.
일반 함수로 호출하면 this는 전역 객체가 바인딩 된다.
var value = 1
const obj= {
value: 100,
foo(){
console.log('foo this: ', this); //{value: 100, foo: ƒ}
setTimeout(function() {
console.log('callback this:', this) //window
console.log('callback this.value:', this.value) //1
}, 100);
}
}
console.log(obj.foo())
콜백함수의 this가 전역 객체를 바인딩하는 것은 문제가 있다.
this가 일치하지 않는다는 것은 중첩함수 또는 헬퍼 함수로 동작하기 어렵게 만든다.
⭕[this 바인딩 일치시키기 위한 방법 1.]
var value = 1
const obj = {
value: 100,
foo(){
const that = this; //this 바인딩(obj)을 변수 that에 할당
setTimeout(() => {
console.log(that.value) //this대신 that을 참조함
}, 100);
}
}
console.log(obj.foo()) //100
⭕[this 바인딩 일치시키기 위한 방법 2.]
var value = 1
const obj= {
value: 100,
foo(){
setTimeout(() => {
console.log(this.value) //1
}, 100);
}
}
console.log(obj.foo())
⭕[this 바인딩 일치시키기 위한 방법 3.]
var value = 1
const obj= {
value: 100,
foo(){
setTimeout(function() {
console.log('callback this.value:', this.value) //100
}.bind(this), 100);
}
}
console.log(obj.foo())
메서드 내부의 this는 메서드를 호출한 객체에 바인딩된다.
❗메서드 내부의 this 메서드가 없는 객체: 메서드를 호출한 객체에 바인딩 됨
메서드는 객체에 포함된 것이 아니라 독립적으로 존재하는 별도 객체이다.
다른 객체의 프로퍼티에 할당하는 것으로 다른 객체의 메서드가 될 수도 있고 일반 변수에 할당하여 일반 함수로 호출될 수도 있다.
const person = {
name: 'lee',
getName() {
return this.name
}
}
console.log(person.getName()) //lee
const anotherPerson = {
name: 'kim'
}
anotherPerson.getName = person.getName
console.log(anotherPerson.getName()) //kim
const getName = person.getName
console.log(getName()) //''
prototype 또한 객체이므로 메서드를 호출 할 수 있다.
프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 마찬가지로 해당 메서드를 호출한 객체에 바인딩 된다.
function Person(name){
this.name = name
}
Person.prototype.getName = function(){
return this.name
}
const me = new Person('lee')
Person.prototype.name = 'Kim'
console.log(Person.prototype.getName()) //kim
function.prototype.apply, bind, call 메서드는 모든 함수가 상속받아서 사용할 수 있다.
각 메서드는 호출할 함수에 인수를 전달하는 방식만 다를 뿐 this로 사용할 객체를 전달하면서 함수를 호출한다.
apply, call의 대표적 사용 용도:
- arguments객체와 같은 유사 배열 객체에 배열 메서드를 사용할 수 없음
- arguments객체는 배열이 아니기 때문에 Array.prototype.slice 같은 배열 메서드를 사용할 수 없으나 apply, call메서드를 사용하면 이용 가능하다.
bind는 함수를 호출하지 않지만, 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
bind의 대표적 사용 용도:
- this와 메서드 내부의 중첩 함수 또는 콜백함수의 this가 불일치하는 문제 해결