반응형

1. 기본적인 this 동작 방식

this는 함수가 호출되는 방식에 따라 값이 달라집니다. 주요한 패턴은 다음과 같습니다.

1.1 전역 컨텍스트에서의 this

 
console.log(this); // 브라우저에서는 Window 객체, Node.js에서는 global 객체
 

전역에서 this를 출력하면 브라우저 환경에서는 window 객체를, Node.js 환경에서는 global 객체를 참조합니다.


1.2 일반 함수에서의 this (엄격 모드와 일반 모드)

function showThis() {
    console.log(this);
}
showThis(); // 브라우저에서는 window, Node.js에서는 global

"use strict";
function strictShowThis() {
    console.log(this);
}
strictShowThis(); // undefined (엄격 모드에서는 `this`가 undefined)
  • 일반 모드: this는 전역 객체(window 또는 global)를 참조합니다.
  • 엄격 모드("use strict"): this는 undefined가 됩니다.

1.3 객체의 메서드에서의 this

const obj = {
    name: "Alice",
    showThis: function () {
        console.log(this.name);
    }
};
obj.showThis(); // "Alice"
  • 메서드를 호출한 객체(obj)가 this가 됩니다.

하지만 함수 내부에서 새로운 함수가 호출되면 this가 바뀔 수 있습니다.

const obj = {
    name: "Alice",
    showThis: function () {
        function inner() {
            console.log(this);
        }
        inner(); // 일반 함수로 호출되므로 `this`는 `window` 또는 `undefined`(엄격 모드) 
    }
};
obj.showThis();
  • 해결 방법:
    1. self 또는 that 변수를 활용 (var self = this;)
    2. .bind(this) 사용
    3. 화살표 함수 사용 (아래에서 설명)

2. 생성자 함수와 this

function Person(name) {
    this.name = name;
}

const p1 = new Person("Alice");
console.log(p1.name); // "Alice"
  • new 키워드를 사용하여 생성자 함수를 호출하면 this는 새로 생성된 객체를 참조합니다.

만약 new 없이 호출하면 this가 전역 객체를 가리키거나(비엄격 모드) undefined(엄격 모드)로 설정됩니다.

const p2 = Person("Bob"); // new 없이 호출
console.log(p2); // undefined
console.log(global.name); // "Bob" (Node.js의 경우)

해결 방법:

  • new 없이 호출될 경우 this가 올바른 객체를 참조하도록 강제하는 패턴 사용
function Person(name) {
    if (!(this instanceof Person)) {
        return new Person(name);
    }
    this.name = name;
}

3. 화살표 함수에서의 this

화살표 함수는 일반 함수와 다르게 this를 바인딩하지 않고, 자신을 포함하는 외부 스코프(렉시컬 스코프)의 this를 사용합니다.

const obj = {
    name: "Alice",
    showThis: function () {
        const arrow = () => {
            console.log(this.name);
        };
        arrow();
    }
};
obj.showThis(); // "Alice"
  • arrow 함수는 obj.showThis()의 this를 유지합니다.

하지만 화살표 함수는 생성자 함수로 사용할 수 없습니다.

const Person = (name) => {
    this.name = name;
};
const p = new Person("Alice"); // TypeError: Person is not a constructor

4. bind, call, apply를 이용한 this 변경

4.1 call()과 apply()

call()과 apply()를 사용하면 특정한 this를 설정하여 함수를 실행할 수 있습니다.

 
function showName() {
    console.log(this.name);
}

const user = { name: "Alice" };
showName.call(user); // "Alice"
showName.apply(user); // "Alice"
  • call(thisArg, arg1, arg2, ...) → 개별 인자로 전달
  • apply(thisArg, [arg1, arg2, ...]) → 배열로 전달

4.2 bind()

bind()는 새로운 함수를 반환하여 이후에 this가 고정된 상태로 실행되도록 합니다.

function showName() {
    console.log(this.name);
}
const user = { name: "Alice" };

const boundFn = showName.bind(user);
boundFn(); // "Alice"
  • bind()를 사용하면 this가 영구적으로 고정됩니다.

5. 이벤트 핸들러에서의 this

5.1 일반 함수에서의 this

const button = document.querySelector("button");
button.addEventListener("click", function () {
    console.log(this); // 클릭된 button 요소를 참조
});

5.2 화살표 함수에서의 this

button.addEventListener("click", () => {
    console.log(this); // window 객체를 참조
});
  • 화살표 함수는 이벤트 핸들러로 사용될 때 this가 window가 되어 문제가 발생할 수 있습니다.

해결 방법:

  • bind(this)를 사용하거나, 일반 함수 표현식을 사용

6. 클래스에서의 this

클래스 메서드에서는 this가 자동으로 인스턴스를 가리킵니다.

class Person {
    constructor(name) {
        this.name = name;
    }
    showName() {
        console.log(this.name);
    }
}
const p = new Person("Alice");
p.showName(); // "Alice"

하지만, 클래스 내부에서 setTimeout 등을 사용할 경우 this가 바뀔 수 있습니다.

class Timer {
    start() {
        setTimeout(function () {
            console.log(this); // window 또는 undefined
        }, 1000);
    }
}
const t = new Timer();
t.start();
  • 해결 방법: bind(this) 또는 화살표 함수 사용
class Timer {
    start() {
        setTimeout(() => {
            console.log(this); // Timer 객체 유지
        }, 1000);
    }
}

7. 정리

호출 방식this 값

전역 실행 (일반 모드) window (브라우저) / global (Node.js)
전역 실행 (엄격 모드) undefined
객체의 메서드 해당 객체
화살표 함수 외부 this를 따름 (렉시컬 this)
생성자 함수 새로 생성된 객체 (new 사용 시)
call / apply 명시적으로 지정된 객체
bind 영구적으로 고정된 this
DOM 이벤트 핸들러 (일반 함수) 이벤트가 발생한 요소
DOM 이벤트 핸들러 (화살표 함수) window

this는 문맥에 따라 다르게 동작하므로, 실행 방식과 함수 선언 형태를 잘 이해해야 합니다.

 

특히 클래스 사용시에 전달값을 함수로해서 this를 사용하는 경우에 바인등을 주의깊게 살피지 않으시면 뜬금없이 에러가 발생하므로 주의깊게 사용하셔야 이상한 동작을 할 경우가 줄어듭니다.

반응형

+ Recent posts