자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수.
this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다. ex) this.name, this.getName 등
메서드는 자신이 속한 객체의 프로퍼티를 참조하고 변경할 수 있어야 한다.
자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 알아야 한다.
function Circle(radius) {
???.radius = radius;
}
// 객체가 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
Circle.prototype.getDiameter = function() {
return 2 * ???.radius;
}
But, 객체를 정의하는 시점에는 아직 인스턴스를 생성하기 이전이므로 객체가 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
이때, this라는 특수한 식별자를 사용한다.
식별자 역할을 하는 this와 this가 가리킬 객체를 바인딩 하는 것.
변수 선언을 했을 때 변수 이름과 확보된 메모리 공간의 주소를 연결하는 것처럼 this와 this가 가리킬 객체를 연결하는 것을 this 바인딩이라고 한다.
this 바인딩은 항상 같은 값을 가리키지 않고 함수 호출 방식에 따라 동적으로 결정된다.
- 일반 함수 호출 -> 전역 객체(window)
- 메서드 호출 -> 메서드를 호출한 객체
- 생성자 함수 호출 -> 인스턴스
- function.prototype.apply/call/bind 메서드에 의한 간접 호출 -> 메서드의 첫번째 인자
전역 객체(window)가 this에 바인딩된다.
중첩 함수, 콜백 함수 등 어떤 함수라도 일반 함수로 호출되면 this에 전역 객체가 바인딩된다.
function foo() {
console.log(this); // window
function bar() {
console.log(this); // window
}
}
메서드 내부의 this는 메서드를 호출한 객체에 바인딩된다.
const person = {
name: 'Lee',
getName() {
return this.name;
}
};
console.log(person.getName()); // Lee
생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다. 생성자 함수를 선언하고 인스턴스를 생성할 땐 new연산자를 사용한다. new연산자를 붙이지 않으면 일반 함수로 동작하여 this도 일반 함수의 this로 동작한다.
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getDiameter = function() {
return 2 * this.radius;
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
// new 연산자를 안쓰면 일반 함수로 동작한다. 일반 함수의 this는 전역 객체를 가리킨다.
const circle3 = Circle(100);
console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20
// 일반 함수 Circle은 return값이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3.getDiameter()); // undefined
console.log(radius); // 100
function.prototype.apply/call/bind 메서드의 첫번째 인수로 전달한 객체에 바인딩된다.
apply, call, bind
: function.prototype의 메서드
apply, call
: 함수를 호출하는 기능
arguments 객체와 같은 유사 배열 객체에 배열 메서드를 사용하는 경우에 사용한다.
function convertArgsToArray() {
const arr = Array.prototype.slice.call(arguments);
return arr;
}
convertArgsToArray(1, 2, 3); // [1, 2, 3]
bind
: 첫번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
중첩함수 또는 콜백 함수를 일반 함수로 호출했을 때 전역 객체가 바인딩되는 것을 앞에서 알아보았다.
하지만 그렇게 되면 메서드 내의 중첩함수 또는 콜백 함수의 this가 메서드를 가리켜야 되는데 전역 객체를 바인딩하게 되므로 문제가 생긴다.
이때, bind()
는 메서드의 this
와 메서드 내부의 중첩 함수 또는 콜백 함수의 this
가 불일치할 때 유용하다.
const obj = {
value: 100,
foo() {
setTimeout(function() {
console.log(this); // window
}, 100);
}
};
const obj = {
value: 100,
foo() {
setTimeout(function() {
console.log(this); // obj
}.bind(this), 100);
}
};
일반 함수를 정의할 때 function 키워드를 많이 사용한다. 하지만 ES6문법이 도입되면서 화살표 함수로 함수를 선언할 수 있다.
// 일반 함수 선언
function foo() {
console.log(this);
}
// 화살표 함수 선언
const foo = () => {
console.log(this);
}
화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 따라서 화살표 함수 내부에서 this를 참조하면 가장 가까운 상위 스코프 함수의 this를 참조하게 된다.
const obj = {
value: 100,
foo() {
setTimeout(() => console.log(this), 100);
}
};