Javascript - this
2024. 2. 4. 12:37ㆍ개인노트-개인공부
목차
- this
- 예시
- 일반 함수안에서 this 호출
- 화살표 함수안에서 this 호출
- call()
- 예시 2
# this
- 일반함수와 화살표 함수에서 각각 다른 방식으로 해석이 됩니다.
- 일반 함수의 this는 호출 위치에서 정의.
- 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의.
렉시컬(Lexical)이란 함수가 동작할 수 있는 유효한 범위를 의미합니다.
## 예시
### 일반 함수안에서 this 호출
this 키워드를 사용.
// 일반 함수의 this는 호출 위치에서 정의.
const user = {
firstName: 'first',
lastName: 'last',
age: 85,
getFullName: function () {
this.firstName;
this.lastName;
return `${this.firstName} ${this.lastName}`;
}
}
console.log(user.getFullName()); // first last
this 대신 user 객체로 수정.
// 일반 함수의 this는 호출 위치에서 정의.
const user = {
firstName: 'first',
lastName: 'last',
age: 85,
getFullName: function () {
return `${user.firstName} ${user.lastName}`;
}
}
console.log(user.getFullName()); // first last
- 위 코드에서 일반함수안에서 this를 사용한 것과 user를 사용한 것과 결과 값은 같습니다.
- 즉, this는 user 객체를 가리킵니다.
- '일반 함수의 this는 호출 위치에서 정의.' 된다는 것은 getFullName 함수가 호출되는 곳은 user.getFullName() 이므로 getFullName()을 호출을 시도한 대상인 user객체 를 가리킵니다.
### 화살표 함수안에서 this 호출
this 키워드를 사용.
// 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의.
const user = {
firstName: 'first',
lastName: 'last',
age: 85,
getFullName: () => {
return `${this.firstName} ${this.lastName}`;
}
}
console.log(user.getFullName()); // undefined undefined
- 자신이 선언된 함수(레시컬) 범위 -> 여기서 '자신'은 getFullName함수를 가리킵니다.
- 즉, 화살표 함수 안의 this는 그 화살표 함수가 선언된 감싸는 외부 함수 범위 안에서 정의됩니다.
- 하지만, 위 예제에서는 this가 선언된 화살표 함수를 감싸는 외부 함수가 없습니다. 그래서 결과는 undefined가 출력되었습니다.
그럼 이번에는 this가 사용된 화살표 함수를 감싸는 외부 함수를 만들어보겠습니다.
// 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의.
function user() = {
this.firstName = 'first2'; // 출력됨
this.lastName = 'last2'; // 출력됨
return {
firstName: 'first',
lastName: 'last',
age: 85,
getFullName: () => {
return `${this.firstName} ${this.lastName}`;
}
}
}
const u = user();
console.log(u.getFullName()); // first2 last2
- 화살표 함수 안의 this는 그 화살표 함수를 감싸는 외부 함수 범위 안에서 정의되므로,
- 외부 함수에 정의한 this.firstName인 first2와 this.lastName인 last2가 출력되었습니다.
만약, getFullName의 함수를 다시 일반 함수로 변경한다면?
// 일반 함수의 this는 호출 위치에서 정의.
function user() = {
this.firstName = 'first2';
this.lastName = 'last2';
return {
firstName: 'first', // 출력됨
lastName: 'last', // 출력됨
age: 85,
getFullName: function () {
return `${this.firstName} ${this.lastName}`;
}
}
}
const u = user();
console.log(u.getFullName()); // first last
- getFullName()이 '호출된 곳' 기준이기 때문에 변수'u'에서 반환된 객체의 firstName인 first와 lastName인 last가 출력됩니다.
## call()
call()를 사용하면 객체가 다른 객체에 속한 메서드를 사용할 수 있습니다.
사전 정의된 JavaScript 메서드입니다.
이렇게 일반 함수에서의 this는 호출 위치에서 정의되기 때문에 또 다른 방법으로 접근해서 이름을 출력할 수 있습니다.
function user() = {
this.firstName = 'first2';
this.lastName = 'last2';
return {
firstName: 'first',
lastName: 'last',
age: 85,
getFullName: function () {
return `${this.firstName} ${this.lastName}`;
}
}
}
const GilDong = {
firstName: 'GilDong',
lastName: 'Hong',
}
const u = user();
console.log(u.getFullName()); // first last
console.log(u.getFullName.call(GilDong)); // GilDong Hong
- 특정한 객체에서 다른 객체가 가지고 있는 메소드를 빌려와서 사용할 수 있습니다.
- GilDong 변수는 getFullName이라는 메소드를 가지고 있지 않은 상태입니다.
- call을 사용하면 getFullName이 호출되는 대상은 이제 'u' 객체가 아니라 'GilDong' 객체가 됩니다.
이처럼 일반함수에서의 this 키워드는 호출위치에서 정의되기 때문에 함수를 다른 객체에 붙여서 사용하는 것도 가능합니다.
## 예시 2
const timer = {
title: 'TIMER!',
timeout() {
console.log(this.title);
}
}
timer.timeout(); // TIMER!
- 배운대로 일반함수에서의 this는 호출위치에서 정의되기 때문에 호출위치는 timeout함수가 호출된 timer.timeout() 이므로 this는 timer 객체가 되고 객체 안의 title을 출력하게 됩니다.
setTimeout을 추가하면..
const timer = {
title: 'TIMER!',
timeout() {
console.log(this.title); // TIMER!
setTimeout(function () {
console.log(this.title); // undefined
}, 1000);
}
}
timer.timeout(); // TIMER!
- setTimeout함수의 콜백으로 넣은 함수는 setTimeout 함수 내부 어딘가에서 호출이 됩니다.
- 일반함수에서의 this는 호출위치에서 정의되기 때문에 this는 setTimeout 함수 내부 어딘가에서 호출된 곳에서 정의됩니다.
- 참고로 우리는 setTimeout 함수의 내부 구조는 모르기 때문에 당연히 콜백으로 넣은 함수 this가 무엇을 가르키는지는 모릅니다. 그렇게 무엇인지 모르는 객체에서 title을 조회했기 때문에 'TIMER!' 가 출력될 수 없습니다.
이렇게 함수안에 또다른 함수가 있는 구조이고 this 키워드를 자주 사용한다면, 일반 함수 보다는 화살표 함수를 사용하는 것이 훨씬 더 적합합니다.
setTimeout 콜백 함수를 일반 함수에서 화살표 함수로 바꾸준다면..
const timer = {
title: 'TIMER!',
timeout() {
console.log(this.title); // TIMER!
setTimeout(() => {
console.log(this.title); // TIMER!
}, 1000);
}
}
timer.timeout(); // TIMER!
- 배운대로 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의됩니다.
- 콜백 함수를 감싸고 있는 외부(상위) 범위는 timeout함수가 감싸고 있으므로 timeout이 됩니다.
- 이 때, timeout함수가 가지고 있는 this 키워드는 timer.timeout()에서 호출시점에 timer객체로 정의 되었으므로, 콜백으로 사용된 화살표 함수 안의 this는 timeout함수의 this 즉, timer 객체를 가리킵니다.
## 정리
- this 키워드는 일반함수에서 화살표 함수에서 해석하는 방법이 다릅니다.
- 일반 함수의 this는 호출 위치에서 정의.
- 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의.
참고
'개인노트-개인공부' 카테고리의 다른 글
html 문서 로드와 이벤트 (1) | 2024.05.12 |
---|---|
JavaScript - 함수 (복습) (1) | 2024.03.10 |
Node vs Element (2) | 2024.01.28 |
javascript - 클로저 (1) | 2024.01.21 |
JavaScript - Events (1) | 2024.01.07 |