2024. 01. 30 > 2025. 06. 23 블로그 A/S 프로젝트🚧 로 추가한 글입니다.
예시를 다듬고, 다양한 상황에서의 this를 알아봅니다.
this란?
- this는 자신이 속한 객체, 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다.
this가 왜 필요할까?
- 메서드는 자신이 속한 객체의 프로퍼티를 참조하고 변경할 수 있어야 한다. ➡️ 이를 위해 메서드는 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.
- 생성자 함수 내부에서는 프로퍼티 또는 메서드를 추가하기 위해 자신이 생성할 인스턴스를 참조할 수 있어야 한다. 하지만 생성자 함수를 정의하는 시점은 인스턴스를 생성하기 이전이므로 생성자 함수가 생성할 인스턴스를 가리키는 식별자를 알 수 없다. ➡️ 이를 위해 자신이 생성할 인스턴스를 가리키는 특수한 식별자가 필요하다.
this는 언제 결정되는가
- this의 값은 런타임에 결정된다.
- 동일한 함수라도 다른 객체에서 호출했다면 this가 참조하는 값이 달라진다.
- 즉 this 바인딩은 동적으로 결정된다.
어디서 호출되었는지에 따라 달라지는 this의 값
호출 위치 | this에 바인딩되는 값 |
전역 호출 | ✔️ 전역 객체 |
일반 함수 호출 | ✔️ 전역 객체 |
메서드 호출 | ✔️ 메서드 소유 객체 X ✔️ 메서드 호출 객체 O |
생성자 함수 호출 | ✔️ 생성자 함수가 생성할 인스턴스 |
call, apply 메서드에 의한 간접 호출 |
✔️ 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체에 this 바인딩 |
bind 메서드에 의한 간접 호출 | ✔️ 함수 호출 X ✔️ 첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환 |
화살표 함수 | ✔️ 고유한 this를 가지지 않음 ✔️ 스코프 체인을 통해 상위 스코프의 this 참조 |
❗️전역 객체란?
✔️ 모든 객체의 최상위 객체. 모든 객체는 이 전역 객체의 프로퍼티이다.
✔️ 브라우저 환경 - window
✔️ Node.js 환경 - global
아래 예시는 Node.js 환경에서 실행했습니다.
전역 호출 ⏩️ 전역 객체가 this
console.log(this === global); // true
일반 함수 호출 ⏩️ 전역 객체가 this
function hello(name) {
console.log(this === global);
}
hello('Ham'); // true
hello('Jam'); // true
메서드 호출 ⏩️ 메서드를 호출한 객체가 this
function sayHello() {
console.log(this);
}
const hello1 = {
name: 'Ham',
sayHello,
};
const hello2 = {
name: 'Jam',
sayHello,
};
hello1.sayHello(); // { name: 'Ham', sayHello: [Function: sayHello] }
hello2.sayHello(); // { name: 'Jam', sayHello: [Function: sayHello] }
생성자 함수 호출 ⏩️ 생성자 함수가 만든 인스턴스가 this
function Hello(name) {
this.name = name;
}
Hello.prototype.sayHello = function () {
console.log(this);
};
const hello1 = new Hello4('Ham');
const hello2 = new Hello4('Jam');
hello1.sayHello(); // Hello { name: 'Ham' }
hello2.sayHello(); // Hello { name: 'Jam' }
중첩 함수의 this? ⏩️ 전역 객체가 this (일반 함수로 호출된다면 무조건!)
const foo = {
getThis() {
setTimeout(function bar() {
console.log(this);
}, 2000);
}
}
foo.getThis(); // window
call/apply/bind
function add(c, d) {
return this.a + this.b + c + d;
}
const o = { a: 1, b: 3 };
// 첫 번째 인자는 'this'로 사용할 객체이고,
// 이어지는 인자들은 함수 호출에서 인수로 전달된다.
add.call(o, 5, 7); // 16
// 첫 번째 인자는 'this'로 사용할 객체이고,
// 두 번째 인자는 함수 호출에서 인수로 사용될 멤버들이 위치한 배열이다.
add.apply(o, [10, 20]); // 34
const foo = {
getThis() {
setTimeout(function bar() {
console.log(this);
}.bind(this), 2000); // 콜백으로 들어간 bar의 this를 getThis()의 this와 바인딩
}
}
foo.getThis(); // foo 객체
화살표 함수 호출 ⏩️ 상위 스코프의 this (외부 렉시컬 환경)
const foo = {
getThis() {
setTimeout(()=>{
console.log(this);
}, 2000);
}
}
foo.getThis(); // foo 객체
이벤트 리스너에서의 this? ⏩️ currentTarget (이벤트 핸들러가 부착된 곳)
function checkThis(e) {
console.log(this === e.currentTarget); // true
}
const body = document.querySelector("body");
body.addEventListener("click", checkThis);
참고자료
모던 자바스크립트 Deep Dive: 자바스크립트의 기본 개념과 동작 원리
269개의 그림과 원리를 파헤치는 설명으로 ‘자바스크립트의 기본 개념과 동작 원리’를 이해하자! 웹페이지의 단순한 보조 기능을 처리하기 위한 제한적인 용도로 태어난 자바스크립트는 과도
wikibook.co.kr
'TIL > JavaScript' 카테고리의 다른 글
실행 컨텍스트 - (1) (0) | 2025.06.27 |
---|---|
[240203] 클로저 (1) | 2024.02.03 |
[240130] 스코프, 스코프 체인, 프로토타입, 프로토타입 체인 (0) | 2024.01.30 |
[240130] 자바스크립트의 객체 생성 방법(객체 리터럴 vs new Object() vs 생성자 함수 vs 클래스) (1) | 2024.01.30 |
[240129] 프로토타입, [[Prototype]] vs __proto__ vs prototype 프로퍼티 (0) | 2024.01.29 |