this 뿌시기

이성훈·2024년 8월 1일

Javascript

목록 보기
9/11
post-thumbnail

모던 자바스크립트 딥 다이브의 내용을 정리한 글입니다.

this란?

자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다. this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.

this 바인딩은 렉시컬 스코프와 결정 시기가 다르다

this 바인딩은 함수 호출 시점에 결정되고, 렉시컬 스코프는 함수 정의가 평가되어 함수 객체가 생성되는 시점에 상위 스코프를 결정

함수 호출 방식에 따른 this

일반 함수

일반 함수로 호출된 모든 함수 내부의 this에는 전역 객체가 바인딩된다.

객체의 메서드

메서드 내부의 this는 메서드를 소유 호출한 객체에 바인딩된다.
객체의 메서드는 객체에 포함된 것이 아니라 독립적로 존재하는 별도의 객체이며, 함수 객체를 가리키고 있다.
객체의 메서드를 화살표 함수로 정의하는 것은 피해야 한다.
메서드를 정의할 때는 ES6 메서드 축약 표현으로 정의한 ES6 메서드를 사용하는 것이 좋다.

const person = {
  name: 'Lee',
  sayHi: () => console.log(`Hi ${this.name}`), // Hi undefined
  sayHello() {
    console.log(`Hello ${this.name}`); // Hello Lee // Good. ES6 메서드 축약 표현
  },
  sayFoo: function () {
    console.log(`Foo ${this.name}`); // Foo Lee
  },
};
person.sayBar = function () {
  console.log(`Bar ${this.name}`); // Bar Lee // 프로퍼티 동적 추가 시 ES6 메서드 정의를 사용할 수 없으므로 일반 함수 할당
};

생성자 함수

생성자 함수 내부 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다.
new 연산자와 함께 호출해야만 한다. 그렇지 않으면 일반 함수로 동작하게 되어 window 객체를 가리키고 return문이 없다면 undefined를 반환한다.

화살표 함수

화살표 함수의 this는 일반 함수의 this와 다르게 상위 스코프의 this를 그대로 참조한다. 화살표 함수는 콜백 함수로 자주 사용되므로 "콜백 함수의 this 문제"를 해결하기 위해 의도적으로 이렇게 동작하도록 설계된 것이다.
class 필드에 할당한 화살표 함수는 프로토타입 메서드가 아니라 인스턴스 메서드가 된다. 따라서 ES6 메서드를 사용하는 것이 좋다.

마치 렉시컬 스코프처럼 함수가 정의된 위치에 의해 결정된다는 뜻에서 이를 lexical this라 한다.

class의 화살표 함수에 관해 아직 이해가 잘 안 된 상태이다. 모던 자바스크립트 딥 다이브 p.485를 이해하자.
클래스에서 이벤트 핸들러 바인딩 - p.793

const func = function () {
  console.log(this); // 호출 방법에 따라 다름
  setTimeout(function () {
    // 콜백이지만 일반 함수로 호출되므로 항상 window 바인딩, 화살표 함수라면 상위 스코프의 this와 일치
    console.log('callback this : ', this); 
  }, 100);
};
func(); // 일반함수로 호출 -> 전역객체 window 바인딩

const obj = { func };
obj.func(); // 객체 메서드 -> 객체 바인딩 {func: ƒ}

new func(); // 생성자 함수 -> 생성될 인스턴스 가리킴 func {}

이벤트 핸들러 내부의 this

이벤트 핸들러 어트리뷰트 방식

 <button onclick="handleClick()">Click me!</button>
function handleClick() {
	console.log(this); // window
}
 <button onclick="handleClick(this)">Click me!</button>
function handleClick(button) {
	console.log(button) // 이벤트를 바인딩한 button 요소
  	console.log(this); // window
}

이벤트 핸들러 프로퍼티 방식 & addEventListener 방식

두 가지 방식 모두 이벤트 핸들러 내부의 this는 이벤트를 바인딩한 DOM 요소(=currentTarget)를 가리킨다.

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
  </head>
  <body>
    <button class="btn1">0</button>
    <button class="btn2">0</button>
  </body>
  <script>
    const $button1 = document.querySelector('.btn1');
    const $button2 = document.querySelector('.btn2');
    $button1.onclick = function (e) {
      console.log(this); // $button1
      console.log(e.currentTarget); // $button1
      console.log(this === e.currentTarget); // true
    };
    $button2.addEventListener('click', function (e) {
      console.log(this); // $button2
      console.log(e.currentTarget); // $button2
      console.log(this === e.currentTarget); // true
    });
  </script>
</html>

클래스에서 이벤트 핸들러를 바인딩 하는 경우 this에 주의해야 한다. - p.793

profile
프론트엔드 정리

0개의 댓글