상황에따른 this 정리
JeongSeulho
2024년 04월 07일

1. this란
모든 함수는 this를 가지고 있으며 this는 어떤 객체를 가르키고 있다. 그리고 this는 함수가 호출되는 상황에 따라 가리키는 어떤 객체가 달라진다.
이렇게 함수가 호출되는 상황에 따라 this가 가리키는 객체가 동적으로 변하는데, 이를 this가 어떤 객체에 바인딩되는 것이라고 한다.
2. this binding rules
this가 어떤 객체를 가리키는지는 아래에서 설명할 규칙에 따라 달라진다.
2.1 기본 바인딩
기본 바인딩은 어떤 객체를 통해 함수가 호출되지 않고 함수가 단독으로 호출되었을 때 규칙이다.
-
브라우저
strict mode인 경우와 아닌 경우의 차이가 있다.
function a(){ console.log(this); } function b(){ 'use strict'; console.log(this); } a(); // object [window] console.log(this); // object [window] b(); // undefined -
Node.js
- 전역 컨텍스트에서 실행되는 경우와 어떤 함수 컨텍스트에서 실행되는 경우의 차이가 있다.
function a(){ console.log(this); } // 함수 컨텍스트 a(); // object [global] // 전역 컨텍스트 console.log(this); // {} console.log(this === module.exports); // true
2.2 암시적 바인딩
함수가 어떤 객체의 메소드로 호출되었을 때, this는 해당 객체를 가리킨다.
하지만, 메소드가 파라미터로 전달되거나 다른 변수에 할당되어 호출되는 경우 암시적 바인딩이 적용되지 않는다.
const obj = {
name: 'seulho',
getName: function(){
console.log(this.name);
}
}
function execute(callback){
callback();
}
obj.getName(); // seulho
// 파라미터로 전달, 암시적 바인딩 적용 X
execute(obj.getName); // undefined
// 변수에 할당, 암시적 바인딩 적용 X
const getName = obj.getName;
getName(); // undefined
.또는[]연산을 사용하여 객체의 속성에 접근하면 참조 타입이라고 하는 어떤 값을 얻게 된다.
이 값에 메소드가 호출된 객체가 있으며 암시적 바인딩이란 이 정보를 사용하여this를 바인딩한다.
위 처럼 파라미터, 변수에 할당을 하게 되면 이 정보들이 같이 전달되지 않고 해당 메소드의 참조값만 전달되기 때문에this가 바인딩 되지 않는다.
2.3 명시적 바인딩
call, apply, bind 메소드를 사용하여 this를 바인딩하는 것을 명시적 바인딩이라고 한다.
const obj = {
name: 'seulho',
getName: function(arg1, arg2){
console.log(this.name, arg1, arg2);
}
}
const obj2 = {
name: 'seulho2'
}
// obj2를 바인딩하여 호출
obj.getName.call(obj2, 'arg1', 'arg2'); // seulho2 arg1 arg2
obj.getName.apply(obj2, ['arg1', 'arg2']); // seulho2 arg1 arg2
// 항상 obj2를 바인딩하는 새로운 함수 생성
// 하드 바인딩
const getNameBindObj2 = obj.getName.bind(obj2, 'arg1', 'arg2');
getNameBindObj2(); // seulho2 arg1 arg22.4 new 바인딩
함수에 new 키워드를 사용하면 3가지 일이 일어난다.
- 새로운 객체가 생성된다. => 여기서
this는 새로 생성된 객체를 가리킨다. - 함수 코드가 실행
- 생성된 새로운 객체 반환
즉, new를 사용하면 this는 새로 생성된 객체를 가리킨다.
function Person(name){
this.name = name;
getName = function(){
console.log(this.name);
}
}
const person = new Person('seulho');
person.getName(); // seulho
const person2 = new Person('seulho2');
person2.getName(); // seulho23. this 바인딩 우선순위
위의 바인딩 규칙은 중복으로 적용되는 경우가 많은데, 이때 this 바인딩 우선순위는 아래와 같다.
new바인딩- 명시적 바인딩
- 암시적 바인딩
- 기본 바인딩
4. 화살표 함수와 this
화살표 함수의 this는 함수가 호출 기준이 아닌 선언될 당시의 상위 실행 컨텍스트의 this를 가리킨다.
const obj = {
name: 'seulho',
getNameInSec() {
setTimeout(function(){
console.log(this.name);
}, 1000);
}
}
obj.getNameInSec(); // undefined위와 같이 함수가 파라미터로 전달되었기 때문에 this는 암시적 바인딩이 적용되지 않아 window 또는 Timeout 객체를 가리키게 된다.
-
지역 변수를 사용하여 해결
const obj2 = { name: 'seulho', getNameInSec() { const that = this; setTimeout(function(){ console.log(that.name); }, 1000); } } obj2.getNameInSec(); // seulho -
bind를 사용하여 해결const obj3 = { name: 'seulho', getNameInSec() { setTimeout(function(){ console.log(this.name); }.bind(this), 1000); } } -
화살표 함수를 사용하여 해결
const obj4 = { name: 'seulho', getNameInSec() { setTimeout(() => { console.log(this.name); }, 1000); } } obj4.getNameInSec(); // seulho