1. this란 무엇인가
this는 현재 실행 중인 컨텍스트(Context) 를 참조하는 특별한 키워드다.
즉, 코드가 “누구의 입장에서 실행되었는가” 에 따라 그 대상이 달라진다.
this는 정의될 때가 아니라, 실행될 때 결정된다.
이게 핵심이야.
2. 전역 컨텍스트에서의 this
브라우저 환경에서는 전역 this가 window 객체를 가리킨다.
console.log(this === window); // true
Node.js에서는 global 또는 module.exports를 가리킨다.
즉, 전역 this는 환경에 따라 다르다.
3. 함수에서의 this (기본 바인딩 규칙)
function showThis() {
console.log(this);
}
showThis(); // window (브라우저) / undefined (strict mode)
✅ 일반 함수 호출에서는 this가 전역 객체를 가리킨다.
✅ 단, 'use strict' 모드에서는 undefined.
4. 객체 메서드에서의 this
const user = {
name: "기범",
sayHello() {
console.log("안녕, 나는", this.name);
},
};
user.sayHello(); // 안녕, 나는 기범
✅ user.sayHello()는 “user 객체의 맥락”에서 실행됨.
✅ 즉, this는 user 객체를 참조한다.
💡 하지만 객체의 메서드를 변수로 분리하면 this가 달라진다.
const greet = user.sayHello;
greet(); // undefined 또는 'window' (this가 사라짐)
이런 현상이 발생하는 이유는,
메서드가 객체에서 떨어져 나가면 **“누가 호출했는가”**의 정보가 사라지기 때문이다.
5. 생성자 함수에서의 this
new 키워드로 함수를 호출하면,
this는 새로 생성되는 인스턴스를 가리킨다.
function User(name) {
this.name = name;
}
const kb = new User("기범");
console.log(kb.name); // 기범
✅ new를 사용하면 내부적으로 다음이 일어난다:
- 새로운 객체 {} 생성
- 그 객체를 this에 바인딩
- 함수 실행
- 객체 반환
6. 명시적 바인딩 — call, apply, bind
this를 수동으로 바꿀 수도 있다.
🔹 call
function greet() {
console.log("안녕, 나는 " + this.name);
}
const user = { name: "기범" };
greet.call(user); // 안녕, 나는 기범
🔹 apply
function introduce(lang1, lang2) {
console.log(`${this.name}는 ${lang1}와 ${lang2}를 사용합니다.`);
}
const dev = { name: "기범" };
introduce.apply(dev, ["JavaScript", "Python"]);
🔹 bind
bind()는 this를 고정한 새 함수를 반환한다.
const bound = greet.bind(user);
bound(); // 안녕, 나는 기범
✅ call과 apply는 즉시 실행
✅ bind는 “묶은 함수”를 나중에 실행
7. 화살표 함수(Arrow Function)에서의 this
화살표 함수는 this를 자체적으로 바인딩하지 않는다.
즉, 상위 스코프의 this를 그대로 상속받는다.
const user = {
name: "기범",
normal() {
console.log(this.name);
},
arrow: () => {
console.log(this.name);
},
};
user.normal(); // 기범
user.arrow(); // undefined (상위 스코프: window)
✅ 화살표 함수는 this가 “고정(bound)”되어 있다.
✅ 따라서 메서드 정의에는 화살표 함수 사용을 피해야 한다.
8. 콜백 함수 안에서의 this 문제
비동기 콜백에서는 this가 종종 의도치 않게 사라진다.
const counter = {
count: 0,
start() {
setTimeout(function () {
console.log(this.count);
}, 1000);
},
};
counter.start(); // undefined
왜냐면 setTimeout 내부의 콜백은 일반 함수 호출로 간주되기 때문이야.
해결 방법은 2가지 👇
✅ 1) 화살표 함수 사용
setTimeout(() => console.log(this.count), 1000);
✅ 2) 변수에 this 저장
const self = this;
setTimeout(function () {
console.log(self.count);
}, 1000);
9. 클래스에서의 this
클래스 내부에서는 this가 해당 인스턴스를 가리킨다.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`안녕, 나는 ${this.name}`);
}
}
const kb = new User("기범");
kb.sayHi(); // 안녕, 나는 기범
하지만 클래스에서도 this가 유실되는 상황이 있다 👇
const say = kb.sayHi;
say(); // ❌ this undefined
해결 방법은 bind로 메서드를 고정하는 것이다.
this.sayHi = this.sayHi.bind(this);
또는 화살표 메서드를 사용해 상위 스코프의 this를 유지할 수도 있다.
class User {
constructor(name) {
this.name = name;
}
sayHi = () => console.log(`안녕, 나는 ${this.name}`);
}
10. 브라우저 이벤트 리스너에서의 this
const btn = document.querySelector("button");
btn.addEventListener("click", function () {
console.log(this); // <button> 요소
});
✅ 일반 함수에서는 this가 “이벤트 대상”을 가리킴.
✅ 화살표 함수에서는 상위 스코프의 this를 사용하므로 버튼이 아님.
btn.addEventListener("click", () => {
console.log(this); // window
});
11. this 바인딩 규칙 요약표
호출 방식 this가 가리키는 대상
| 전역 | window / global |
| 일반 함수 | window (strict 모드에서는 undefined) |
| 객체 메서드 | 호출한 객체 |
| 생성자 함수 | 새로 생성된 인스턴스 |
| call / apply / bind | 명시적으로 지정된 객체 |
| 화살표 함수 | 상위 스코프의 this |
| 클래스 메서드 | 인스턴스 |
| 이벤트 핸들러 (function) | 이벤트 발생한 요소 |
| 이벤트 핸들러 (arrow) | 상위 스코프 |
12. 실무 예제 — React에서의 this
React의 클래스형 컴포넌트는 this를 정확히 이해해야 동작한다.
class App extends React.Component {
constructor() {
super();
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ count: this.state.count + 1 });
}
render() {
return <button onClick={this.handleClick}>{this.state.count}</button>;
}
}
✅ bind(this)를 하지 않으면 this가 undefined가 되어 setState 호출 불가
✅ 함수형 컴포넌트의 useState와 useEffect는 이 문제를 근본적으로 제거함
13. 마무리
이제 자바스크립트의 this가
**“정의 시점이 아니라 실행 시점에 결정된다”**는 걸 명확히 이해했을 거야.
모든 헷갈림은 결국 “누가 함수를 호출했는가”를 생각하면 풀린다.
“this를 이해하지 못하면 자바스크립트는 마법처럼 보이지만,
이해하면 논리적인 언어가 된다.”
'frontend > javascript' 카테고리의 다른 글
| 🟨 2-19. 프로토타입(Prototype) 완벽 가이드 — 자바스크립트 객체지향의 뼈대 구조 이해하기 (0) | 2025.11.07 |
|---|---|
| 🟨 2-18. 클로저(Closure) 완전 정복 — 함수형 자바스크립트의 핵심 개념과 실무 응용 (0) | 2025.11.07 |
| 🟨 2-16. 자바스크립트 이벤트 루프와 콜스택 — 비동기 코드의 진짜 실행 순서 이해하기 (0) | 2025.11.07 |
| 🟨 2-15. 이벤트 위임 실전 활용 — 성능과 유지보수를 모두 잡는 동적 이벤트 처리법 (1) | 2025.11.07 |
| 🟨 2-14. 이벤트 버블링과 캡처링 완벽 이해 — 브라우저 이벤트 흐름의 핵심 메커니즘 (0) | 2025.11.07 |