프로그래밍-학습기록/Javascript

Array 메소드(filter, find 등)의 반환 값을 잘 알아두자.

leesche 2021. 3. 11. 23:58

오늘은 이런 일이 있었다.

결론부터 말하자면, Array.filter 메소드의 반환 값이 배열이란 것을 몰라서 일어난 경험이다.

상황은 다음과 같은 함수에서 일어났다.

export default class ScoreManager {
    /* ... */
  score(player) {
        console.log(player)
    this.#playerScore[player.getType()] += 1;
    const $score = Array.from(this.$scores).find(($score) => $score.id === player.getType());
    $score.textContent = this.getScore(player);
  }
    /* ... */
}

어떤 문제인지, 아래 score(player) 메소드에서 player의 getType() 메소드를 호출하지 못한다는 에러가 발생했다.

 

인자로 받은 player가 잘못되었나 했지만 player를 콘솔 로그에 출력한 결과 player 객체라고 출력됐다. 이게 무슨 일인가?

score 메소드는 아래 클래스 인스턴스의 메소드에서 호출됐다.

export default class GameManager {
    /* ... */ 
    isGameEnd() {
        if (Judge.isGameEnd(this.#gameBoard.getAllMarks())) {
                /* ... */
          const winnerType = Judge.getWinnerType(this.#gameBoard.getAllMarks());
          if (winnerType) {
            const players = [this.#player1, this.#player2];
            const winner = players.filter((player) => player.getType() === winnerType); // 문제의 코드
            this.#scoreBoard.score(winner);
            this.#handleWin(winnerType);
            return true;
          }
          this.#handleDraw();
          return true;
        }
        return false;
      }
    /* ... */
}

그래, filter로 조건에 맞는 player를 걸러내서 score의 인자로 전달했는데 뭐가 문제인 거야?

앞서 말했듯이, filter가 문제였다. filter는 player를 반환하는 것이 아니었다. filter는 조건에 맞는 player가 담긴 배열을 반환했다. 위 console.log 출력문에서 [Player]를 자세히 보면 알 수 있겠지만 대놓고 배열이었고, 그것을 펼쳐보면 떡하니 Array라고 적혀 있었다 ...

하지만 나는

"filter면 player가 걸러지니까 그걸 바로 전하면 되지 않을까~?"

하고 안일하게 생각해버린 것이다.

이 상황에서는 filter가 아니라 조건에 맞는 요소 하나를 반환하는 find 메소드를 써야 했다.

/* ... */
const winner = players.find((player) => player.getType() === winnerType);
/* ... */

메소드를 사용할 때는 대충 생각하지 말고 심사숙고해서 사용하자. 버그가 발생한다면, 콘솔 출력문도 주의 깊게 살피자.