자바로 개발을 했을 당시에 내가 알던 this는 현재 객체만을 참조한다 정도였다. 그렇기 때문에 자바스크립트로 개발을 할 때도 this가 그런건가 보다.. 라고 생각을 했는데 너무나도 동떨어진 생각이였다.
자바스크립트의 this는 자바와 달리 동적으로 this의 값이 달라져 생각보다 복잡하다. 나름 골치아픈 주제라 정리를 해보자.
this란 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 식별자를 참조할 수 있는 키워드다.
위에서 언급했듯이, 자바스크립트에서 this는 계속 값이 달라진다. 그러면 언제 this의 값이 정해지는 걸까?
바로 함수가 호출되는 그 시점에 this의 값이 정해진다.
const a = 'hello';
function abc() {
console.log(this); // window
console.log(this.a); // hello
}
// 일반 함수 호출
abc();
const obj = {
value: 10,
method: function() {
console.log(this); // { value: 10, method: [Function: method] }
console.log(this.value); // 10
}
};
obj.method();
const Obj = function() {
console.log(this); // Obj
};
const foo = new Obj("foo");
const obj = {
value: 10,
method: function() {
console.log(this); // obj
const innerMethod = () => {
console.log(this); // obj
console.log(this.value); // 10
};
innerMethod();
}
};
obj.method();
여기서 이상한 점이 보이는가? 분명히 innerMethod(); 로 호출 즉, 일반 함수 호출이기 때문에 전역 객체인 window 객체가 바인딩 되어야 하는데, innerMethod 함수의 this는 obj이다.
그 이유는 간단한데 innerMethod는 화살표 함수이기 때문이다. 화살표 함수는 예외를 가진다.
위의 내용들을 통해 함수의 종류에 따라 this의 값이 달라지는 것을 확인했다. 그렇다면 this의 값을 내가 원하는 대로 바꿀 수 있을까?
당연히 가능하다. 즉, this의 값을 강제로 바꿀 수 있다.
크게 3가지가 있는데 하나씩 살펴보자.
const obj = {
value: 42
};
function printValue(a, b) {
console.log(this); // obj { value: 42 }
console.log(this.value); // 42
console.log(a, b); // 1 2
}
printValue.apply(obj, [1, 2]);
const obj = {
value: 42
};
function printValue(a, b) {
console.log(this); // obj { value: 42 }
console.log(this.value) // 42
console.log(a, b); // 1 2
}
printValue.call(obj, 1, 2);
여기서 apply와 call을 간단하게 정리해보겠다.
const obj = {
value: 42
};
function printValue(a, b) {
console.log(this); // obj
console.log(this.value); // 42
console.log(a, b); // 1, 2
}
const boundFunction = printValue.bind(obj, 1);
boundFunction(2);
printValue.bind(obj, 1); 를 통해 printValue의 this를 obj로 바인딩하고, 첫 번째 인자가 1인 새로운 함수를 생성한다.
즉, bind 메서드는 함수의 this를 특정 객체로 고정하고, 일부 인자를 미리 설정할 때 유용하다.