[Javascript] This 마스터하기

insung·2025년 4월 13일

자바스크립트에서 this는 객체지향 언어의 this와는 다르게 함수를 호출한 방법에 따라 결정.

이 때문에 많은 개발자들이 헷갈리는 개념 중 하나이다.

1. 자바스크립트에서 this는 호출된 방식에 따라 결정된다

예제 1: 함수 호출 방식에 따라 달라지는 this

const car = {
  brand: "현대",
  getBrand: function () {
    console.log("car getBrand", this);
  },
};

car.getBrand(); *// 여기서 this -> car 객체*
const globalCar = car.getBrand;

globalCar(); *// 여기서 this -> window 객체*
  • car.getBrand()this는 car 객체를 가리킴. 호출 주체가 car이기 때문.
  • globalCar()this는 전역 객체(window)를 가리킴. 호출 주체가 전역 스코프이기 때문.

예제 2: 호출 주체에 따라 달라지는 this

const car2 = {
  brand: "기아",
  getBrand: car.brand,
};

car2.getBrand(); *// 여기서 this -> car2 객체*
  • 호출 주체가 car2이므로, this는 car2를 가리킴

예제 3: 이벤트 핸들러에서의 this

<body>
  <button id="button">this는 누굴까?</button>
</body>

const btn = document.getElementById("button");
btn.addEventListener("click", car.getBrand);
*// 결과: 버튼 태그 자체가 출력됨*
  • 이벤트 핸들러에서의 this: 이벤트를 발생시킨 주체(btn)를 가리킴

2. 호출 방식에 따라 바뀌는 this, 어떻게 해결할까?

해결 방법 1: bind로 고정하기

const bindGetBrand = car2.getBrand.bind(car); *// this를 car로 고정*
bindGetBrand(); *// this -> car*

btn.addEventListener("click", car.getBrand.bind(car)); *// this -> car*
  • bind()를 사용하면 특정 객체로 this를 고정할 수 있음

해결 방법 2: 화살표 함수 사용

화살표 함수는 상위 스코프의 this를 계승.

따라서 일반 함수와 다르게 호출 방식에 영향을 받지 않음

const testCar = {
  brand: "benz",
  getBrand: function () {
    console.log("getbrand", this.brand);
    const innerFunc = () => {
      console.log("innerFunc", this.brand);
    };
    innerFunc(); *// 상위 스코프의 this를 계승받아 testCar를 가리킴*
  },
};

testCar.getBrand(); 
*// getbrand -> 'benz'// innerFunc -> 'benz'*

면접에서 자주 나오는 문제

문제 1: 일반 함수 안에서의 this

const testCar = {
  brand: "benz",
  getBrand: function () {
    console.log("getbrand", this.brand);
    const innerFunc = function () {
      console.log("innerFunc", this.brand);
    };
    innerFunc(); 
  },
};

testCar.getBrand();
*// getbrand -> 'benz'// innerFunc -> undefined (윈도우 객체의 brand는 없음)*

해결 방법

  1. bind() 사용

    const testCar = {
      brand: "benz",
      getBrand: function () {
        console.log("getbrand", this.brand);
        const innerFunc = function () {
          console.log("innerFunc", this.brand);
        }.bind(this); *// this를 고정*
        innerFunc();
      },
    };
    
    testCar.getBrand();
  2. 화살표 함수 사용

    const testCar = {
      brand: "benz",
      getBrand: function () {
        console.log("getbrand", this.brand);
        const innerFunc = () => {
          console.log("innerFunc", this.brand);
        };
        innerFunc();
      },
    };
    
    testCar.getBrand();

문제 2: 배열 메서드와 this

const ageTest = {
  unit: "살",
  ageList: [10, 20, 30],
  getAgeList: function () {
    const result = this.ageList.map(function (age) {
      return age + this.unit;
    });

    console.log(result); 
    *// 결과: [NaN, NaN, NaN] (윈도우 객체의 unit은 undefined)*
  },
};

해결 방법

  1. 화살표 함수 사용

    const ageTest = {
      unit: "살",
      ageList: [10, 20, 30],
      getAgeList: function () {
        const result = this.ageList.map((age) => age + this.unit);
        console.log(result); *// 결과: ['10살', '20살', '30살']*
      },
    };
    
    ageTest.getAgeList();

결론 및 정리

  1. 일반 함수 사용 시
    • 호출 방식에 따라 달라지는 this. 예측 가능한 코드를 작성하려면 bindcall, 또는 apply*로 명시적으로 고정하자.
  2. 화살표 함수 사용 시
    • 화살표 함수는 상위 스코프의 this를 계승하므로, 내부 함수에서 유용하게 사용할 수 있다.
    • 단, 화살표 함수는 bindcall, 또는 apply를 사용할 수 없다.

추가적으로 알아두면 좋은 메서드

callapply

  • 명시적으로 호출 주체(this)를 설정할 수 있는 메서드.
  • 차이점:
    • call(): 인수를 쉼표로 구분하여 전달.
    • apply(): 인수를 배열 형태로 전달.
const bindGetBrand = car2.getBrand.bind(car); *// bind* 
car2.getBrand.call(car, 인수1, 인수2, ...); *// call*
car2.getBrand.apply(car, [인수1, 인수2, ...]); *// apply*
profile
안녕하세요 프론트엔드 관련 포스팅을 주로 하고 있습니다

0개의 댓글