개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

this — 호출 방식과 바인딩 규칙

2025년 8월 25일
JavaScriptthis바인딩화살표 함수

JavaScript에서 this는 생각보다 훨씬 자주 예상을 벗어납니다. 분명히 객체 안에 있는 함수인데 this가 undefined이거나, 콜백으로 넘겼더니 갑자기 window를 가리킵니다. 그 이유는 this가 어디에 썼느냐가 아니라 어떻게 호출됐느냐로 결정되기 때문입니다.

this란 무엇인가

this는 함수가 실행되는 시점에 결정되는 현재 실행 문맥을 가리키는 키워드입니다. 코드를 작성할 때가 아니라 실제로 함수가 호출될 때 값이 정해집니다.

declaration time → this: unresolved
call time        → this: resolved

이 한 가지 원칙을 이해하면 아래에 나오는 모든 케이스가 자연스럽게 따라옵니다.

전역에서의 this

브라우저 환경에서 전역 스코프의 this는 window 객체입니다. Node.js에서는 global 또는 모듈 컨텍스트에서 빈 객체 {}를 가리킵니다.

// 브라우저
console.log(this === window); // true

// Node.js (모듈 아닌 스크립트)
console.log(this === global); // true

메서드 호출 — this는 점 앞의 객체

객체의 메서드로 함수를 호출하면 this는 그 객체를 가리킵니다.

const user = {
  name: "김철수",
  greet() {
    console.log(`안녕하세요, ${this.name}입니다.`);
  },
};

user.greet(); // 안녕하세요, 김철수입니다.

user.greet처럼 점(.) 앞에 있는 객체가 this로 바인딩됩니다.

바인딩(Binding): this가 어떤 객체를 가리킬지 확정하는 과정.

일반 함수 호출 — 전역 또는 undefined

객체 없이 단독으로 호출한 함수의 this는 전역 객체(window)이거나, strict mode에서는 undefined입니다.

strict mode: "use strict" 선언 또는 ES 모듈 환경에서 활성화되며, 일반 함수 호출 시 this를 undefined로 만들어 실수를 방지합니다.

메서드 안 중첩 함수 함정

const timer = {
  seconds: 0,
  start() {
    console.log(this); // timer 객체 (올바름)

    function tick() {
      this.seconds += 1; // this는 window 또는 undefined (오류)
      console.log(this.seconds);
    }

    tick(); // 일반 함수 호출이므로 this가 끊김
  },
};

timer.start();

start는 메서드 호출이라 this가 timer이지만, 내부의 tick은 일반 함수 호출이라 this가 전역 객체로 바뀌어 버립니다. 이것이 흔히 말하는 중첩 함수 함정입니다.

메서드 분리 호출 — this 단절

const user = {
  name: "이영희",
  greet() {
    console.log(this.name);
  },
};

const fn = user.greet;
fn(); // undefined (this가 window 또는 undefined)

user.greet를 변수에 담는 순간 객체와의 연결이 끊어집니다. fn은 이제 일반 함수 호출이기 때문에 this가 전역 객체를 가리킵니다. 콜백으로 메서드를 넘길 때 가장 자주 발생하는 실수입니다.

call / apply / bind — 명시적 this 지정

this를 직접 지정하고 싶을 때 사용하는 세 가지 메서드입니다.

call과 apply

function introduce(age, city) {
  console.log(`이름: ${this.name}, 나이: ${age}, 도시: ${city}`);
}

const person = { name: "박민준" };

introduce.call(person, 30, "서울");
// 이름: 박민준, 나이: 30, 도시: 서울

introduce.apply(person, [30, "서울"]);
// 이름: 박민준, 나이: 30, 도시: 서울

call과 apply의 첫 번째 인수로 넘긴 객체가 this가 됩니다. 두 메서드의 차이는 인수 전달 방식뿐입니다. call은 인수를 쉼표로 나열하고, apply는 인수를 배열로 전달합니다. 둘 다 함수를 즉시 실행합니다.

bind

const boundIntroduce = introduce.bind(person, 30);
boundIntroduce("부산");
// 이름: 박민준, 나이: 30, 도시: 부산

bind는 원본 함수를 변경하지 않고 this와 일부 인수를 고정한 새 함수를 반환합니다. 즉시 실행하지 않으므로 나중에 호출할 때 사용합니다.

메서드실행 시점인수 형태
call즉시 실행쉼표 나열
apply즉시 실행배열
bind나중에 실행쉼표 나열 (부분 적용 가능)

화살표 함수 — 렉시컬 this 바인딩

화살표 함수는 자신만의 this를 갖지 않습니다. 선언된 시점의 외부 스코프 this를 그대로 캡처합니다.

중첩 함수 함정 해결

const timer = {
  seconds: 0,
  start() {
    const tick = () => {
      this.seconds += 1; // 화살표 함수이므로 start()의 this = timer (올바름)
      console.log(this.seconds);
    };

    tick();
  },
};

timer.start(); // 1

화살표 함수 메서드 사용 금지

const user = {
  name: "최수진",
  greet: () => {
    console.log(this.name); // undefined (오류)
  },
};

user.greet();

화살표 함수는 this를 외부에서 캡처합니다. 객체 리터럴의 외부는 전역 스코프이므로 this가 window(또는 undefined)가 됩니다. 메서드는 반드시 일반 함수로 선언해야 합니다.

클래스에서의 this

클래스 내부 메서드에서 this는 인스턴스를 가리킵니다. 단, 콜백으로 넘기면 끊어집니다.

class Counter {
  constructor() {
    this.count = 0;
  }

  increment() {
    this.count += 1;
    console.log(this.count);
  }
}

const counter = new Counter();

// 콜백으로 넘기면 this가 끊김
setTimeout(counter.increment, 1000); // NaN (오류)

해결 방법 1 — bind

setTimeout(counter.increment.bind(counter), 1000); // 1 (올바름)

해결 방법 2 — 클래스 필드 화살표 함수

class Counter {
  count = 0;

  increment = () => {
    this.count += 1;
    console.log(this.count);
  };
}

const counter = new Counter();
setTimeout(counter.increment, 1000); // 1 (올바름)

클래스 필드로 화살표 함수를 정의하면 생성자 실행 시점에 this가 인스턴스로 고정됩니다.

요약

개념핵심
this 결정 시점선언 시점이 아닌 호출 시점
바인딩this가 가리킬 객체를 확정하는 과정
중첩 함수 함정일반 함수 호출로 this가 전역으로 바뀌는 현상
해결책화살표 함수 또는 bind 사용
호출 방식this
전역 스코프window (브라우저) / global (Node.js)
일반 함수 호출window 또는 undefined (strict mode)
메서드 호출 (obj.fn)obj
메서드 분리 호출window 또는 undefined
call / apply첫 번째 인수로 지정한 객체
bindbind 시 지정한 객체 (고정)
화살표 함수선언 시점의 외부 스코프 this

스코프와 렉시컬 환경은 코드를 작성한 위치를 기준으로 동작하지만, this는 반대로 함수가 호출된 시점과 방식을 기준으로 결정됩니다. 같은 함수인데 this가 달라지는 상황 대부분은 작성 위치와 호출 방식을 혼동한 데서 비롯됩니다.

← 이전 글실행 컨텍스트 — 코드가 실행되는 환경
다음 글 →클로저 — 렉시컬 환경을 기억하는 함수