SDWoo
SDWoo의 개발일기
SDWoo
전체 방문자
오늘
어제
  • 분류 전체보기 (21)
    • 데브코스 (4)
    • TIL (13)
    • javascript (4)
    • react (0)
    • 알고리즘 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • deepdiv
  • vanilaJS
  • 무한스크롤
  • Promise
  • Typing-Game
  • 이벤트루프
  • es6
  • intersectionobserver
  • 비동기
  • 디스트럭처링할당
  • 제네레이터
  • 행맨
  • 호이스팅
  • JavaScript #TIL #VanillaJS
  • addEventListener
  • async/await
  • 프로그래머스
  • 신규 아이디 추천
  • linkedlist
  • vanillajs
  • cypress
  • JavaScript
  • Spread문법
  • RESTAPI 설계 원칙 #까먹지말것
  • javascrip
  • 선형
  • 알고리즘
  • 데브코스
  • This
  • Til

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
SDWoo

SDWoo의 개발일기

[JavaScript] addEventListener에서의 this 바인딩
javascript

[JavaScript] addEventListener에서의 this 바인딩

2022. 8. 18. 16:23

오늘은 20 web Projects중 hangman을 VanillaJS 로 구현하고, Component형식으로 바꾸던 와중.
this바인딩 때문에 고생했던 기억을 이겨내고자 정리를 해보려고한다.

Code

먼저 html에서 module type으로 index.js를 받아오기로 했다.

// index.js
import App from './App.js';
const app = new App(document.querySelector('.App'));
window.addEventListener('keydown', app.handleKeyDown);

 

이렇게 index.js 에서 window.addEventListner를 호출하고,
'keydown' 이벤트가 일어나면. App.js의 handleKeyDown 메소드를 호출하려고 한다.

 

// App.js
export default class App {
  constructor($app) {
  ...
  }

  ...

  handleKeyDown(e) {
    const { answer, correctLetters, wrongLetters } = this.state;
    if (e.keyCode < 65 || e.keyCode > 90) {
      return;
    }
    const letter = e.key;

    if (correctLetters.includes(letter) || wrongLetters.includes(letter)) {
      this.setState({
        ...this.state,
        Notification: true,
      });
      return;
    }

    if (answer.includes(letter)) {
      this.setState({
        ...this.state,
        correctLetters: [...this.state.correctLetters, letter],
        wrongCount: wrongLetters.length,
        isPopup: correctLetters.length + 1 === answer.length,
        message: 'Congratulations! You won! 😃',
        isNotification: false,
      });
    } else {
      this.setState({
        ...this.state,
        wrongLetters: [...this.state.wrongLetters, letter],
        wrongCount: wrongLetters.length,
        isPopup: wrongLetters.length + 1 === 5,
        message: 'Unfortunately you lost. 😕',
        isNotification: false,
      });
    }
  }

 

이렇게 App.js에서 this.state를 쓰려하는데, this가 window를 가리켜서 this.state 가 없는 놈이 되버린 것이다.😱
이 이유가 무엇일까를 계속해서 고민해 보았다.

 

🤭  이유

이것의 이유는 window.addEventListener('keydown', app.handleKeyDown)을 했을 때,

addEventListener 안에서의 this 는 e.currentTarget과 같으므로 전역 객체인 window를 가리키게 된 것이다!!

 

👊 해결방법

해결 방법은 constructor에서 this.handleKeyDonw에 현재 App.js의 this 를 .bind 함수를 통해 바인딩 해주면 된다 ㅎ

 

코드는 이렇다.

export default class App {
  constructor($app) {
    this.state = {
      isPopup: false,
      message: '',
      isNotification: false,
      wrongLetters: [],
      wrongCount: 0,
      correctLetters: [],
      answer: WORDS[Math.floor(Math.random() * WORDS.length)],
    };

    ...

    this.handleKeyDown = this.handleKeyDown.bind(this);
  }
  
...

  handleKeyDown(e) {
    const { answer, correctLetters, wrongLetters } = this.state;
    console.log(e.currentTarget);
    if (e.keyCode < 65 || e.keyCode > 90) {
      return;
    }
    const letter = e.key;

    if (correctLetters.includes(letter) || wrongLetters.includes(letter)) {
      this.setState({
        ...this.state,
        Notification: true,
      });
      return;
    }

    if (answer.includes(letter)) {
      this.setState({
        ...this.state,
        correctLetters: [...this.state.correctLetters, letter],
        wrongCount: wrongLetters.length,
        isPopup: correctLetters.length + 1 === answer.length,
        message: 'Congratulations! You won! 😃',
        isNotification: false,
      });
    } else {
      this.setState({
        ...this.state,
        wrongLetters: [...this.state.wrongLetters, letter],
        wrongCount: wrongLetters.length,
        isPopup: wrongLetters.length + 1 === 5,
        message: 'Unfortunately you lost. 😕',
        isNotification: false,
      });
    }
  }

 

'javascript' 카테고리의 다른 글

💪REST API 설계 원칙  (0) 2022.09.28
[JavaScript] JavaScript 로 TDD 및 테스트 코드 작성 하기 (cypress)  (0) 2022.08.15
JavaScript로 알고리즘 준비하기(1) - 정규 표현식(문자열 갖고놀기)  (0) 2022.04.14
    'javascript' 카테고리의 다른 글
    • 💪REST API 설계 원칙
    • [JavaScript] JavaScript 로 TDD 및 테스트 코드 작성 하기 (cypress)
    • JavaScript로 알고리즘 준비하기(1) - 정규 표현식(문자열 갖고놀기)
    SDWoo
    SDWoo

    티스토리툴바