자바스크립트의 this는 잘 정리해두지 않으면 혼란스러운 개념입니다. this는 어디서든 사용할 수 있습니다. this는 자신을 호출한 주체에 대한 정보를 가리킵니다. 그러나 상황에 따라 this가 바라보는 대상이 달라집니다.
전역 공간에서의 this는 전역 객체
를 가리킵니다. 전역 객체의 이름은 자바스크립트 런타임 환경에 따라 다른 이름과 정보를 가지고 있습니다.
window
global
각 환경의 전역 공간에서 console.log(this) 를 출력해보면 가지고 있는 정보가 다릅니다.
먼저 함수를 실행하는 방법을 구분할 수 있어야 합니다. 함수를 실행하는 일반적인 방법에는 함수로서 호출하는 방법과 메서드로서 호출하는 방법이 있습니다. 둘을 구분하는 유일한 차이점은 독립성
입니다. 함수로서 호출하는 경우는 그 자체로 독립적인 기능을 수행하지만, 메서드로서 호출하는 함수는 자신을 호출한 대상 객체에 관한 기능을 수행합니다.
const fn = function() {
console.log(this);
}
// 함수로서 호출
fn(); //Window {...}
const obj = {
method: fn
}
// 메서드로서 호출
obj.method(); //{method: f}
함수앞에 .(점)이 있는지 여부로 함수로서의 호출인지 메서드로서의 호출인지 구분할 수있습니다. 즉, 어떤 함수를 호출할 때 그 함수 이름앞에 객체가 명시되어 있으면 메서드로 호출한 것이고, 이외의 모든 경우는 함수로서 호출한 것입니다.
메서드 호출 방법
점 표기법: obj.method()
대괄호 표기법: obj['method']
메서드 내부에서의 this는, 메서드를 호출한 주체(객체)를 가리킵니다. 점 표기법으로 호출한 경우에는 마지막 점 앞의 객체가 곧 this가 됩니다.
const obj = {
methodA: function() {
console.log(this)
},
inner: {
methodB: function() {
console.log(this)
}
}
}
obj.methodA(); //{ methodA: f, inner: {...} }
obj.inner.methodB(); //{ methodB: f }
함수 내부에서의 this는 전역 객체를 가리킵니다.
이 부분에서 this의 사용에 혼란이 생기기 쉽습니다. 앞의 함수로서의 호출과 메서드로서의 호출을 잘 구분할 줄 안다면 this가 가리키는 대상을 따라가기 쉽습니다.
var obj1 = {
outer: function() {
console.log(this);
var innerFunc = function() {
console.log(this);
}
innerFunc();
var obj2 = {
innerMethod: innerFunc
}
obj2.innerMethod(); //obj2
}
}
obj1.outer();
console에는 다음과 같이 출력됩니다.
obj1 { outer: f }
Window {...}
obj2 { innerMethod: f }
함수는 function 키워드로 선언할 수 있고 화살표 함수로도 선언할 수 있습니다.그러나 일반 함수와 화살표 함수 내에서 this의 해석이 다릅니다. 일반 함수의 this는 호출 위치에서 정의되고, 화살표 함수의 this는 상위 스코프에서 상속됩니다.
const user = {
name: '홍길동',
age: 20,
getUser: function(){
return `${this.name} ${this.age}`
}
}
console.log(user.getUser()) // 홍길동 20
여기서 this는 user 객체를 의미하게 됩니다.
const user = {
name: '홍길동',
age: 20,
getUser: () => {
return `${this.name} ${this.age}`
}
}
console.log(user.getUser()) // undefined undefined
this 키워드를 감싸는 함수의 상위에 있는 함수는 없습니다. 따라서 this는 undefined를 가집니다. 위의 코드를 다음과 같이 수정해보겠습니다.
function user() {
this.name = "홍길순"
this.age = 30
return {
name: '홍길동',
age: 20,
getUser: () => {
return `${this.name} ${this.age}`
}
}
}
const user_obj = user();
console.log(user_obj.getUser()) // 홍길순 30
getUser 메서드 안의 this는 상위 user 함수를 참조하여 값을 상속받습니다.