simoong·blog

자바스크립트 this 키워드 완전 정리: 개념부터 실무 예제까지

완전 정리! 자바스크립트 this 키워드 가이드

자바스크립트에서 this 키워드는 정말 헷갈리면서도 중요한 개념이에요.
저도 처음 자바스크립트를 공부할 때는 "아니 도대체 이게 왜 이렇게 동작하지?" 하면서 머리를 쥐어뜯은 기억이 있어요 😅
하지만 차근차근 원리를 이해하고 다양한 예제를 접하다 보면, this는 오히려 자바스크립트를 더 자유롭고 강력하게 만들어주는 도구라는 걸 깨닫게 돼요.

이번 글에서는 this의 기본 개념 → 실행 컨텍스트 → 전역/함수/메서드/클래스/화살표 함수 → call/apply/bind → 이벤트/타이머 → 실무 사례(React, Vue, Node.js) → FAQ 까지 아주 풍부하게 다뤄볼 거예요.


📌 this 키워드란 무엇인가요?

한 줄 정의: this는 함수가 호출될 때 결정되는 실행 컨텍스트의 참조 값이에요.

많은 언어에서 this는 "현재 객체"를 가리킨다고 설명하지만, 자바스크립트는 다릅니다.
자바스크립트에서는 함수가 어떻게 호출되었는지(call site) 에 따라 this가 달라져요.
이게 헷갈림의 핵심이에요.


📌 실행 컨텍스트와 this

자바스크립트 코드는 실행될 때 실행 컨텍스트(Execution Context) 라는 환경 안에서 동작해요.
각 실행 컨텍스트에는 다음 정보가 들어있어요:

  • 변수 환경 (Variable Environment)
  • 렉시컬 환경 (Lexical Environment)
  • this 바인딩

👉 즉, this의 값은 실행 컨텍스트가 생성될 때 결정돼요.
이제 각각의 상황에서 어떻게 달라지는지 살펴봅시다!


📌 전역 컨텍스트에서의 this

// 브라우저
console.log(this) // window
 
// Node.js
console.log(this) // {}
  • 브라우저: 전역 객체 window
  • Node.js: 모듈 시스템 때문에 빈 객체 {}

👉 이미 여기서부터 혼란이 시작돼요. 같은 코드라도 환경에 따라 다르게 동작하거든요.


📌 일반 함수 호출에서의 this

function showThis() {
  console.log(this)
}
 
showThis()
  • 엄격 모드가 아닐 때: window (브라우저 전역 객체)
  • 엄격 모드('use strict')일 때: undefined
'use strict'
function strictModeTest() {
  console.log(this)
}
strictModeTest() // undefined

👉 즉, 엄격 모드 여부에 따라 this 값이 확 달라져요.


📌 객체 메서드 호출에서의 this

const user = {
  name: '철수',
  greet() {
    console.log(`안녕하세요, 저는 ${this.name}이에요!`)
  }
}
 
user.greet() // 안녕하세요, 저는 철수이에요!

👉 여기서는 thisuser 객체를 가리켜요.
즉, 메서드를 소유한 객체가 this가 된다는 규칙이 적용돼요.

❌ 자주 하는 실수

const hello = user.greet
hello() // 엄격 모드: undefined / 비엄격 모드: window

👉 이렇게 메서드를 변수에 담아 호출하면 this가 깨져요!

✅ 해결: bind 사용

const helloBound = user.greet.bind(user)
helloBound() // 안녕하세요, 저는 철수이에요!

📌 중첩 객체에서의 this

const team = {
  name: '개발팀',
  member: {
    name: '영희',
    introduce() {
      console.log(`저는 ${this.name}이에요!`)
    }
  }
}
 
team.member.introduce() // 저는 영희이에요!

👉 여기서 this는 member 객체를 가리켜요.
즉, 점(.) 앞에 오는 객체가 누구인지에 따라 결정돼요.


📌 생성자 함수와 클래스에서의 this

생성자 함수

function Person(name) {
  this.name = name
}
 
const p1 = new Person('민수')
console.log(p1.name) // 민수

👉 new를 사용하면 새로운 객체가 만들어지고, 그 객체가 this가 돼요.

클래스

class Car {
  constructor(model) {
    this.model = model
  }
  show() {
    console.log(`이 차는 ${this.model}이에요!`)
  }
}
 
const c = new Car('Tesla')
c.show() // 이 차는 Tesla이에요!

📌 화살표 함수에서의 this

화살표 함수는 자신만의 this를 가지지 않고, 상위 스코프의 this를 그대로 사용해요.

const obj = {
  name: '홍길동',
  say: () => {
    console.log(this.name)
  }
}
 
obj.say() // undefined

👉 여기서 this는 obj가 아니라 전역(window)을 참조해요.

올바른 활용 예시

function Timer() {
  this.seconds = 0
  setInterval(() => {
    this.seconds++
    console.log(this.seconds)
  }, 1000)
}
 
new Timer()

👉 화살표 함수 덕분에 setInterval 안에서도 바깥 this(Timer 인스턴스)를 사용할 수 있어요.


📌 call, apply, bind로 this 바꾸기

function introduce(age) {
  console.log(`${this.name}, ${age}살이에요.`)
}
 
introduce.call({ name: '지영' }, 25) // 지영, 25살이에요.
introduce.apply({ name: '민호' }, [30]) // 민호, 30살이에요.
 
const boundFunc = introduce.bind({ name: '수지' }, 28)
boundFunc() // 수지, 28살이에요.

👉 정리:

  • call → 즉시 실행, 인자 리스트 전달
  • apply → 즉시 실행, 인자 배열 전달
  • bind → 새 함수 반환

📌 이벤트 핸들러에서의 this

<button id="btn">Click</button>
 
<script>
document.getElementById('btn').addEventListener('click', function() {
  console.log(this) // 버튼 요소
})
</script>

👉 여기서 this는 이벤트가 걸린 요소를 가리켜요.

⚠️ 하지만 화살표 함수를 쓰면 달라져요:

document.getElementById('btn').addEventListener('click', () => {
  console.log(this) // window
})

📌 setTimeout / setInterval에서의 this

setTimeout(function() {
  console.log(this) // window
}, 1000)

👉 해결: 화살표 함수 사용

setTimeout(() => {
  console.log(this) // 상위 스코프의 this
}, 1000)

📌 React에서의 this

클래스 컴포넌트

class Counter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
    this.increment = this.increment.bind(this)
  }
 
  increment() {
    this.setState({ count: this.state.count + 1 })
  }
 
  render() {
    return <button onClick={this.increment}>클릭 {this.state.count}</button>
  }
}

👉 bind를 해주지 않으면 this가 undefined가 돼요.
👉 함수형 컴포넌트에서는 화살표 함수 + hooks로 해결돼요.


📌 Vue에서의 this

new Vue({
  data() {
    return { msg: 'Hello' }
  },
  methods: {
    show() {
      console.log(this.msg)
    }
  }
})

👉 Vue 2에서는 this가 컴포넌트 인스턴스를 가리켜요.
👉 Vue 3 Composition API에서는 this 대신 setup() 반환값을 사용하죠.


📌 Node.js에서의 this

console.log(this) // {}
 
function normal() {
  console.log(this)
}
normal() // undefined (strict mode)

👉 Node.js는 모듈 시스템 때문에 전역 this가 다르게 동작해요.


📌 this가 헷갈리는 대표적인 20가지 예제

  1. 전역 함수 호출
  2. 엄격 모드 함수 호출
  3. 객체 메서드 호출
  4. 메서드 분리 후 호출
  5. 중첩 객체
  6. 생성자 함수
  7. 클래스
  8. 클래스 메서드 분리
  9. 화살표 함수
  10. 화살표 함수 + setTimeout
  11. call
  12. apply
  13. bind
  14. 이벤트 핸들러 (일반 함수)
  15. 이벤트 핸들러 (화살표 함수)
  16. setInterval 안 this
  17. React 클래스 컴포넌트
  18. React 함수형 컴포넌트 (hook 활용)
  19. Vue 2 Options API
  20. Node.js 모듈 스코프

👉 각 상황을 직접 실행해보면서 익히면 머리에 쏙 들어와요!


❓ FAQ: this 관련 자주 묻는 질문

  1. 자바스크립트에서 this는 무엇인가요?
  2. 엄격 모드에서 함수 호출 시 this는 왜 undefined인가요?
  3. 화살표 함수의 this는 어떻게 결정되나요?
  4. 객체 메서드를 분리해서 호출하면 왜 this가 깨지나요?
  5. call, apply, bind 차이는 뭔가요?
  6. 이벤트 핸들러에서 this는 무엇을 가리키나요?
  7. setTimeout 안 this는 왜 window인가요?
  8. React 클래스 컴포넌트에서 this 바인딩은 왜 필요한가요?
  9. Vue 3에서는 this를 왜 쓰지 않나요?
  10. Node.js에서 전역 this는 왜 {} 인가요?

📚 참고 자료


✅ 마무리

자바스크립트의 this호출 방식에 따라 달라지는 동적 키워드예요.
헷갈리지만, 다양한 예제와 실무 사례를 경험하다 보면 자연스럽게 익숙해질 거예요.

👉 이제는 this가 더 이상 무섭지 않죠? 🚀