this — 호출 방식에 따라 달라지는 자바스크립트의 핵심 키워드
자바스크립트를 배우다 보면 헷갈리는 개념 중 하나가 바로 this다.
같은 코드처럼 보여도 어떻게 호출했느냐에 따라 가리키는 대상이 달라지기 때문이다.
이번 글에서는 this의 본질과 동작 방식을 직관적으로 정리해본다.
1. this란 무엇인가?
this는 자기 자신을 참조하기 위한 변수다.
자바스크립트 엔진이 함수를 실행할 때마다 암묵적으로 생성하며, 함수 내부에서 지역 변수처럼 사용할 수 있다.
this는 자신이 속한 객체 또는 생성될 인스턴스를 가리키며, 그 바인딩은 함수를 어떻게 호출했는지에 따라 동적으로 결정된다.
2. 왜 this가 필요한가?
1. 객체의 메서드가 자기 자신을 참조하기 위해
const person = {
name: "Jay",
greet() {
console.log(`안녕하세요, ${this.name}입니다.`);
},
};
person.greet(); // Jay
this가 없다면 person.name처럼 객체 이름을 직접 적어야 하는데, 코드가 복잡해지면 이런 방식은 유지보수가 어렵다.
2. 생성자 함수는 정의 시점에 인스턴스가 존재하지 않기 때문
function User(name) {
this.name = name; // this는 생성될 인스턴스
}
const jay = new User("Jay");
console.log(jay.name); // Jay
3. 객체 이름을 직접 참조하는 것은 비추천
객체가 다른 변수에 할당되거나, 구조가 바뀌면 참조가 깨질 수 있기 때문. 따라서 this는 객체 자신을 안전하게 참조하는 방식이다.
3. 함수 호출 방식에 따른 this 바인딩
자바스크립트에서 this의 값은 정의 시점이 아니라 호출 시점에 결정된다.
아래는 가장 자주 쓰이는 네 가지 호출 방식이다.
1. 일반 함수 호출
function normalFunc() {
console.log("일반 함수:", this);
}
normalFunc();
- this → 전역 객체 (브라우저 환경에서는 window 그리고 Node.js 환경에서는 globalThis)
- 단, "use strict" 모드에서는 undefined가 된다.
- 즉, 일반 함수에서는 this가 의미 없는 값일 가능성이 높다.
use strict 모드 ?
"use strict" 모드에서 일반 함수의 this가 undefined가 되는 이유는,
의도치 않게 전역 객체(window나 global)가 참조되는 것을 방지하기 위해서이다.
기본적으로 자바스크립트는 일반 함수를 호출할 때 this를 전역 객체로 자동 바인딩하지만, 엄격 모드에서는 이런 암묵적 바인딩을 막고 this를 undefined로 설정하여 전역 오염(전역 객체에 불필요한 프로퍼티가 추가되는 문제)을 방지하고, 더 안전하고 예측 가능한 코드를 작성할 수 있게 하는 것이다.
1. Non-strict 모드의 문제점 예시 코드
function setName(name) {
this.name = name; // ❗ 전역 객체(window)에 프로퍼티 추가됨
}
setName("Jay");
console.log(window.name); // "Jay"
함수 내부에서 this를 잘못 사용했지만, 에러가 나지 않고 전역 공간이 오염된다.
2. Strict 모드 개선 예시 코드
"use strict";
function setName(name) {
this.name = name; // ❗ TypeError 발생 (this가 undefined)
}
setName("Jay");
// 👉 TypeError: Cannot set property 'name' of undefined
자바스크립트가 “이건 전역 객체가 아니야. 잘못된 접근이야!” 라고 알려주어 의도하지 않은 전역 오염을 원천 차단한다.
2. 메서드 호출
const person = {
name: "Jay",
greet() {
console.log("메서드:", this.name);
},
};
person.greet(); // person 이 greet 메소드를 호출함
여기에서 this 는 메서드를 호출한 객체 (person) 이다.
주의할 점은, “메서드를 소유한 객체”가 아니라 “호출한 객체” 가 기준이라는 것이다.
아래의 경우를 보면,
const fn = person.greet;
fn(); // 일반 함수 호출 → this는 전역 객체
fn()은 주체 없이 단순히 함수를 호출했을 뿐이므로, this가 person을 잃고 전역 객체를 가리킨다.
3. 생성자 함수 호출
function User(name) {
this.name = name;
console.log("생성자:", this);
}
const user1 = new User("Jay");
- this → 새로 생성된 인스턴스 (user1)
- new 연산자와 함께 호출될 때만 적용된다.
- this는 자동으로 새 객체에 바인딩되며,
- 함수 내부에서 프로퍼티를 정의하면 그것이 인스턴스에 추가된다.
4. 객체 이름을 직접 참조하는 비추천 방식
const circle = {
radius: 5,
getDiameter() {
// ❌ circle.radius 대신 this.radius 사용 권장
return this.radius * 2;
},
};
console.log("지름:", circle.getDiameter());
- 객체 이름(circle)을 직접 참조하면,
- 나중에 변수가 바뀌거나 재사용할 때 문제가 생긴다.
- this는 현재 호출된 객체를 자동으로 참조하므로 더 안전하다.
4. this 바인딩 요약표
호출 방식 | this가 가리키는 대상 |
일반 함수 호출 | 전역 객체 (window / globalThis) 또는 undefined (strict mode) |
메서드 호출 | 메서드를 호출한 객체 |
생성자 함수 호출 | 새로 생성된 인스턴스 |
화살표 함수 | 상위 스코프의 this (렉시컬 this) |
화살표 함수의 this는 고정된다.
즉, 호출 방식과 상관없이 자신이 정의된 위치의 this를 그대로 사용한다.
5. 정리 및 마무리
- this는 함수 실행 시점에 자동으로 바인딩되는 자기참조 변수다.
- 호출 방식에 따라 달라지며, 이는 자바스크립트의 동적 바인딩 특성을 보여준다.
- this를 잘못 이해하면 메서드 분실, 의도치 않은 전역 참조 등의 버그가 발생한다.
- 따라서 메서드 내부에서는 항상 객체 이름 대신 this를 사용하고, 상황에 따라 화살표 함수의 렉시컬 this를 적절히 활용해야 한다.
this는 자바스크립트의 함수형 언어적 특성과 객체지향적 특성을 이어주는 핵심 개념이다.
함수가 어떻게 호출되는지, 그리고 그 시점의 실행 컨텍스트를 이해하면 더 이상 this가 낯설지 않을 것이다.