프론트엔드/JavaScript

(JavaScript) 10. this와 실행 컨텍스트

그린티_ 2025. 5. 2. 12:16
반응형

JavaScript에서 this는 함수가 호출되는 방식에 따라 달라진다고 볼 수 있음

"누가" 호출했느냐에 따라 달라지며, 객체/전역/콜백/화살표 함수/클래스 등에서 전부 다르게 바인딩될 수 있음

 

1️⃣ this 바인딩의 기본 개념

this는 "현재 실행 중인 함수가 속한 객체"를 참조하는 키워드

실행 방식에 따라 this 값이 달라짐!

전역에서 (strict mode X) window (globalThis in Node.js)
객체의 메서드 해당 객체
일반 함수 호출 window (strict mode에서는 undefined)
bind(), call(), apply() 사용 지정한 객체로 변경
화살표 함수 (=>) 상위 스코프의 this를 유지

2️⃣ this 바인딩 예제

(1) 전역 실행

console.log(this); // 브라우저: window, Node.js: globalThis

브라우저 환경에서는 window 객체를 가리킴

Node.js에서는 globalThis를 가리킴

(2) 객체 메서드 호출

const obj = {
    name: "Alice",
    sayHello: function() {
        console.log(this.name);
    }
};

obj.sayHello(); // "Alice"

객체의 메서드에서 this는 해당 객체를 가리킴 (obj)

Java에서는

  • this는 항상 현재 인스턴스를 가리킴
  • 어떤 방식으로 메서드를 호출해도, this는 그 메서드가 속한 객체를 가리키는 건 같다고 생각했음!
public class User {
    String name;
    public void printName() {
        System.out.println(this.name); // 항상 현재 객체의 name
    }
}

(3) 일반 함수 호출

function sayHello() {
    console.log(this);
}

sayHello(); // 브라우저: window, Node.js: undefined (strict mode)

일반 함수에서 this는 window (또는 undefined in strict mode)

"이 함수가 어디에 속해 있느냐" 가 아니라 "어떻게 호출되었느냐" 가 중요!

(4) bind(), call(), apply()로 this 변경

const person = { name: "Bob" };

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

const sayBob = sayHello.bind(person);
sayBob(); // "Bob"

bind()를 사용하면 this를 특정 객체(person)에 고정할 수 있음

call()과 apply()도 비슷하지만, 즉시 실행됨

sayHello.call(person); // "Bob"
sayHello.apply(person); // "Bob"

(5) 화살표 함수 (=>)

const obj = {
    name: "Charlie",
    sayHello: function() {
        const inner = () => {
            console.log(this.name);
        };
        inner();
    }
};

obj.sayHello(); // "Charlie"

화살표 함수는 this를 자신이 속한 스코프에서 유지함!

즉, inner()의 this는 obj.sayHello()의 this(obj)와 동일!

3️⃣ this와 비동기 실행 (주의할 점!)

비동기 코드(setTimeout, Promise, async/await)에서 this가 변경될 수 있음

const obj = {
    name: "Eve",
    sayHello: function() {
        setTimeout(function() {
            console.log(this.name); // ❌ undefined (this가 window를 가리킴)
        }, 1000);
    }
};
obj.sayHello();

해결 방법: 화살표 함수 사용 (this 유지됨)

const obj = {
    name: "Eve",
    sayHello: function() {
        setTimeout(() => {
            console.log(this.name); // ✅ "Eve" (this가 obj를 유지)
        }, 1000);
    }
};
obj.sayHello();

4️⃣ this와 클래스

클래스에서 메서드를 호출할 때도 this가 다르게 바인딩될 수 있음

class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(this.name);
    }
}

const p = new Person("David");
p.sayHello(); // "David"

 

클래스의 메서드는 this가 인스턴스 객체(p)를 가리킴

하지만, 메서드를 다른 변수에 할당하면 this가 undefined가 될 수도 있음

const greet = p.sayHello;
greet(); // ❌ undefined (this가 바뀜!)

해결 방법: bind() 사용하기

const greetBound = p.sayHello.bind(p);
greetBound(); // ✅ "David"

 

화살표 함수로 메서드 정의하기

class Person {
    constructor(name) {
        this.name = name;
    }
    sayHello = () => {
        console.log(this.name);
    };
}

 

반응형