[JavaScript] this 란?

YJ·2023년 6월 26일
0

먼저, this는 왜 등장하게 된 걸까?

객체 지향 프로그래밍(object-oriented programming(OOP))에서 지금 여기 이 class안에 있는 속성값을 가져오겠다고 알려주기 위해 this를 사용한다.

그런데 이 this가 자바스크립트에서는 좀 다르게 사용된다. 그러니까 고정값이 아니라 자꾸 바뀌는데! 도대체 어디를 가리키고 있는건지 너무 헷갈려...

그래서 우선,

문서에서 this를 어떻게 설명하고 있는지 찾아봤더니

"대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정됩니다. 실행중에는 할당으로 설정할 수 없고 함수를 호출할 때마다 다를 수 있습니다."
라고 돼있다.

더 혼란스러워지기 전에 예시를 들어 살펴보자.

// 예제 1  
const car = {
   name: 'KIA',
   getName: function () {
     console.log("car getName", this);
   }
}

car.getName();    // {name: 'KIA', getName: f} → 내가 있는 곳! 이 객체!를 this라고 한다고 했으므로 car객체 그 자체가 출력됨
// 예제 2
const globalCar = car.getName;

globalCar();     // window 객체가 출력됨 

예제 1에서는 car가 getName()을 부른 형태인데(car.getName())
예제 2에서는 누가 불렀는지 앞에 아무런 멘션이 없는 형태이다(globalCar()). 그러므로 바깥 최상단인 window 객체(전역 객체)가 불렀다고 판단되어 this 객체로 window가 지정된 것이다.

그러므로 this 는 고정된 것이 아니라, 함수가 호출될 때 결정된다.
즉, 누가 호출했느냐에 따라 this의 값이 바뀐다.(해당 함수를 호출하는 구문 앞에 점(또는 대괄호)이 있는지 없는지가 관건)

// 예제 3
const car2 = {
   name: 'hyundai',
   getName: car.getName
}

car2.getName();     // {name: 'hyundai', getName: f}

예제 3에서 이제 완벽하게 확인할 수 있다.
car2에 의해 즉, car2가 this를 호출했으므로(car2.getName()) this는 car2객체로 지정되었다.

또 다른 극적인 예를 들어보자.

<!--예제 4-->
<button id="button">Who is THIS?</button>
const btn = document.getElementById("button");
btn.addEventListener("click", car.getName);     // <button id="button">Who is THIS?</button> → 버튼 태그 그 자체가 나와버림!

예제 4에서는 버튼이 eventlistener를 통해 getName을 호출했기 때문에(btn.) 결과로 button 태그 그 자체가 출력된 것이다.

그런데 this 값이 이렇게 계속 바뀌면 어떻게, 뭘 믿고 쓸 수 있을까...

그으래서! this의 값을 고정시켜주기 위해 .bind 함수를 사용한다.

// 예제 5
const bindGetName = car2.getName.bind(car);

bindGetName();    // {name: 'KIA', getName: f}

예제 3예제 5의 차이가 보이십니까?

여기서 하나 더☝🏼

// 예제 6
const testCar = {
  name: 'benz',
  getName: function () {
    console.log("getName", this.name);       // 'getName' 'benz'
    const innerFunc = function () {
      console.log("innerFunc", this.name);   // 'innerFunc' '' → 여기서 this는 window 객체를 가리킨다.
    };
    
    innerFunc();
  };
};

testCar.getName();

예제 6에서 getName과 innerFunc의 this를 같게 만들고 싶으면 어떻게 해야 할까?
아까처럼 .bind를 통해 고정해도 되지만,

화살표 함수를 사용할 수도 있다!

// 예제 6 변형
const testCar = {
  name: 'benz',
  getName: function () {
    console.log("getName", this.name);       // 'getName' 'benz'
    const innerFunc = () => {
      console.log("innerFunc", this.name);   // 'innerFunc' 'benz'
    };
    
    innerFunc();
  };
};

testCar.getName();

여기서 확인할 수 있는 사실은,
화살표 함수에서의 this는 함수가 속해있는 곳의 상위 this를 계승받는다는 점이다.

✏️ 정리해보면, 일반 함수에서의 this와 화살표 함수에서의 this는 다르다!!

일반 함수에서의 this가 호출한 녀석에 의해 결정되었다면, 화살표 함수에서의 this는 상위 함수의 this를 계승받는다. (참고로 화살표 함수는 bind함수를 제공하지 않는다.)

🙋🏻‍♀️ 그럼 나는 this를 쓰고 싶을 때 무슨 함수를 써야 할까?

일반적으로 this를 쓰고 싶다면 일반 함수를 써라.
.bind() 로 원하는 객체를 지정해줄 수 있기 때문에 좀 더 예측 가능한 this로 만들 수 있다.
대신, 함수 안에 있는 함수의 경우에는 상위의 것을 그대로 받아 오는 경우가 많기 때문에 화살표 함수로 만들어 주는 것이 좋다.


※ 참고 자료
코어 자바스크립트
https://youtu.be/tDZROpAdJ9w

profile
Hello

0개의 댓글