블랙커피스터디 함수코드 클래스로 분해 및 extends 사용

KHW·2021년 4월 22일
0

블랙커피스터디

목록 보기
5/9

기존 코드 (module화 진행하지 않았을때)

const $ = (selector) => document.querySelector(selector);
const $All = (selector) => document.querySelectorAll(selector);

const [carButtonDom, tryButtonDom] = $All(".btn-cyan");
const [carNameDom, tryNumberDom] = $All(".w-100");
const progressTitle = $(".mt-4");
const resultDom = $All(".mt-5")[2];
const sectionRaceTimes = $("#section-race-times");

const setting = (carName) => ` <div class="mr-2">
            <div class="car-player">${carName}</div>
            <div class="d-flex justify-center mt-3">
              <div class="relative spinner-container">
                <span class="material spinner"></span>
              </div>
            </div>
          </div>`;

const moving = `<div class="forward-icon mt-2">⬇️️</div>`;

const Message = {
  success: "🎇🎇🎇🎇축하합니다!🎇🎇🎇🎇",
  overFiveError:
    "유효하지 않은 이름 길이입니다. 자동차의 이름은 1자이상, 5자 이하만 가능합니다",
  countError:
    "입력한 레이싱 횟수가 너무 적습니다. 레이싱 횟수는 1이상이어야 합니다.",
};

const result = (winnerName) => `
          <div>
          <h2>🏆 최종 우승자: <span id="winners">${winnerName}</span> 🏆</h2>
          <div class="d-flex justify-center">
            <button type="button" class="btn btn-cyan" id="restart">다시 시작하기</button>
          </div>
          </div>
`;

const carButtonHandler = () => {
  carNameArray = splitCarName(carNameDom.value);
  carNameArray.map((val) => {
    checkOverFiveError(val);
  });
  applyOverFiveError();
};

const tryButtonHandler = () => {
  tryNumber = tryNumberDom.value;
  if (tryNumber < 1) return alert(Message.countError);
  startRacing(tryNumber, carNameArray);
  tryButtonDom.disabled = true;
};

const carButtonEvent = carButtonDom.addEventListener("click", carButtonHandler);
const tryButtonEvent = tryButtonDom.addEventListener("click", tryButtonHandler);

let carNameArray, tryNumber;
let isSmallerFive = true;

const splitCarName = (val) => val.split(",");
const checkOverFiveError = (val) => {
  if (val.length > 5 || val.length < 1) {
    alert(Message.overFiveError);
    isSmallerFive = false;
  }
};
const applyOverFiveError = () => {
  if (isSmallerFive) {
    carButtonDom.disabled = true;
    sectionRaceTimes.hidden = false;
  } else {
    isSmallerFive = true;
  }
};

const startRacing = (tryNumber, carName) => {
  let count = 0;
  carName.map((val) => (progressTitle.innerHTML += setting(val)));
  const carMovingDom = $All(".car-player");
  timerCheck(count, carName, tryNumber, carMovingDom);
};

let isGo = [];

let tryObject = {};

const timerCheck = (count, carNameArray, tryNumber, carMovingDom) => {
  tryObject.count = count;
  tryObject.tryNumber = tryNumber;
  tryObject.timer = setInterval(() => {
    isGo = carNameArray.map(() =>
      Math.floor(Math.random() * 10) >= 4 ? true : false
    );
    goCarMove(carNameArray, isGo, carMovingDom);
    tryObject.count++;
    compareCountAndTryNumber(tryObject);
  }, 1000);
};

let maxCarName = [];
let countArray = {};
let max = -Infinity;

const compareCountAndTryNumber = (tryObject) => {
  if (tryObject.count === Number(tryObject.tryNumber)) {
    clearInterval(tryObject.timer);
    $All(".relative").forEach((x) => x.remove());
    checkWinner();
    resultDom.innerHTML = result(maxCarName);
    $All(".btn-cyan")[2].addEventListener("click", returnToOriginalHandler);
    setTimeout(() => {
      alert(Message.success);
    }, 2000);
  }
};

const returnToOriginalHandler = () => {
  initializeDom();
  initializeValue();
  initializeAttr();
};

const initializeDom = () => {
  while (progressTitle.hasChildNodes()) progressTitle.firstChild.remove();
  while (resultDom.hasChildNodes()) resultDom.firstChild.remove();
};

const initializeValue = () => {
  countArray = {};
  max = -Infinity;
  maxCarName = [];
  $("#inputCarName").value = "";
  $("#inputTryNumber").value = "";
};

const initializeAttr = () => {
  sectionRaceTimes.hidden = true;
  carButtonDom.disabled = false;
  tryButtonDom.disabled = false;
};

const goCarMove = (carNameArray, isGo, carMovingDom) => {
  carNameArray.map((val, idx) => {
    if (countArray[val] !== undefined)
      countArray[val] = isGo[idx] ? ++countArray[val] : countArray[val];
    else countArray[val] = isGo[idx] ? 1 : 0;
    addMovingDom(isGo, idx, carMovingDom);
  });
};

const addMovingDom = (isGo, idx, carMovingDom) => {
  if (isGo[idx]) carMovingDom[idx].insertAdjacentHTML("afterend", moving);
};

const checkWinner = () => {
  for (const idx in countArray) {
    if (max < countArray[idx]) {
      maxCarName = [];
      maxCarName.push(idx);
      max = countArray[idx];
    } else if (max === countArray[idx]) {
      maxCarName.push(idx);
      max = countArray[idx];
    }
  }
};

기존 코드를 Class로 함수를 묶어서 처리할때

const $ = (selector) => document.querySelector(selector);
const $All = (selector) => document.querySelectorAll(selector);

const [carButtonDom, tryButtonDom] = $All(".btn-cyan");
const [carNameDom, tryNumberDom] = $All(".w-100");
const progressTitle = $(".mt-4");
const resultDom = $All(".mt-5")[2];
const sectionRaceTimes = $("#section-race-times");

const setting = (carName) => ` <div class="mr-2">
            <div class="car-player">${carName}</div>
            <div class="d-flex justify-center mt-3">
              <div class="relative spinner-container">
                <span class="material spinner"></span>
              </div>
            </div>
          </div>`;

const moving = `<div class="forward-icon mt-2">⬇️️</div>`;

const Message = {
  success: "🎇🎇🎇🎇축하합니다!🎇🎇🎇🎇",
  overFiveError:
    "유효하지 않은 이름 길이입니다. 자동차의 이름은 1자이상, 5자 이하만 가능합니다",
  countError:
    "입력한 레이싱 횟수가 너무 적습니다. 레이싱 횟수는 1이상이어야 합니다.",
};

const result = (winnerName) => `
          <div>
          <h2>🏆 최종 우승자: <span id="winners">${winnerName}</span> 🏆</h2>
          <div class="d-flex justify-center">
            <button type="button" class="btn btn-cyan" id="restart">다시 시작하기</button>
          </div>
          </div>
`;

const carButtonHandler = () => {
  carNameArray = splitCarName(carNameDom.value);
  carNameArray.map((val) => {
    checkOverFiveError(val);
  });
  applyOverFiveError();
};

const tryButtonHandler = () => {
  tryNumber = tryNumberDom.value;
  if (tryNumber < 1) return alert(Message.countError);
  let car = new Car();
  car.startRacing(tryNumber, carNameArray);
  tryButtonDom.disabled = true;
};

const carButtonEvent = carButtonDom.addEventListener("click", carButtonHandler);
const tryButtonEvent = tryButtonDom.addEventListener("click", tryButtonHandler);

let carNameArray, tryNumber;
let isSmallerFive = true;

const splitCarName = (val) => val.split(",");
const checkOverFiveError = (val) => {
  if (val.length > 5 || val.length < 1) {
    alert(Message.overFiveError);
    isSmallerFive = false;
  }
};
const applyOverFiveError = () => {
  if (isSmallerFive) {
    carButtonDom.disabled = true;
    sectionRaceTimes.hidden = false;
  } else {
    isSmallerFive = true;
  }
};

let isGo = [];

let tryObject = {};

class Car {
  constructor() {}

  startRacing = (tryNumber, carName) => {
    let count = 0;
    carName.map((val) => (progressTitle.innerHTML += setting(val)));
    const carMovingDom = $All(".car-player");
    this.timerCheck(count, carName, tryNumber, carMovingDom);
  };
  timerCheck = (count, carNameArray, tryNumber, carMovingDom) => {
    tryObject.count = count;
    tryObject.tryNumber = tryNumber;
    tryObject.timer = setInterval(() => {
      isGo = carNameArray.map(() =>
        Math.floor(Math.random() * 10) >= 4 ? true : false
      );
      this.goCarMove(carNameArray, isGo, carMovingDom);
      tryObject.count++;
      this.compareCountAndTryNumber(tryObject);
    }, 1000);
  };

  compareCountAndTryNumber = (tryObject) => {
    if (tryObject.count === Number(tryObject.tryNumber)) {
      clearInterval(tryObject.timer);
      $All(".relative").forEach((x) => x.remove());
      this.checkWinner();
      resultDom.innerHTML = result(maxCarName);
      $All(".btn-cyan")[2].addEventListener(
        "click",
        this.returnToOriginalHandler
      );
      setTimeout(() => {
        alert(Message.success);
      }, 2000);
    }
  };

  returnToOriginalHandler = () => {
    this.initializeDom();
    this.initializeValue();
    this.initializeAttr();
  };

  initializeDom = () => {
    while (progressTitle.hasChildNodes()) progressTitle.firstChild.remove();
    while (resultDom.hasChildNodes()) resultDom.firstChild.remove();
  };

  initializeValue = () => {
    countArray = {};
    max = -Infinity;
    maxCarName = [];
    $("#inputCarName").value = "";
    $("#inputTryNumber").value = "";
  };

  initializeAttr = () => {
    sectionRaceTimes.hidden = true;
    carButtonDom.disabled = false;
    tryButtonDom.disabled = false;
  };

  goCarMove = (carNameArray, isGo, carMovingDom) => {
    carNameArray.map((val, idx) => {
      if (countArray[val] !== undefined)
        countArray[val] = isGo[idx] ? ++countArray[val] : countArray[val];
      else countArray[val] = isGo[idx] ? 1 : 0;
      this.addMovingDom(isGo, idx, carMovingDom);
    });
  };

  addMovingDom = (isGo, idx, carMovingDom) => {
    if (isGo[idx]) carMovingDom[idx].insertAdjacentHTML("afterend", moving);
  };

  checkWinner = () => {
    for (const idx in countArray) {
      if (max < countArray[idx]) {
        maxCarName = [];
        maxCarName.push(idx);
        max = countArray[idx];
      } else if (max === countArray[idx]) {
        maxCarName.push(idx);
        max = countArray[idx];
      }
    }
  };
}

let maxCarName = [];
let countArray = {};
let max = -Infinity;

class Car를 통해 함수들을 넣었다.


class 상속처리

const $ = (selector) => document.querySelector(selector);
const $All = (selector) => document.querySelectorAll(selector);

const [carButtonDom, tryButtonDom] = $All(".btn-cyan");
const [carNameDom, tryNumberDom] = $All(".w-100");
const progressTitle = $(".mt-4");
const resultDom = $All(".mt-5")[2];
const sectionRaceTimes = $("#section-race-times");

const setting = (carName) => ` <div class="mr-2">
            <div class="car-player">${carName}</div>
            <div class="d-flex justify-center mt-3">
              <div class="relative spinner-container">
                <span class="material spinner"></span>
              </div>
            </div>
          </div>`;

const moving = `<div class="forward-icon mt-2">⬇️️</div>`;

const Message = {
  success: "🎇🎇🎇🎇축하합니다!🎇🎇🎇🎇",
  overFiveError:
    "유효하지 않은 이름 길이입니다. 자동차의 이름은 1자이상, 5자 이하만 가능합니다",
  countError:
    "입력한 레이싱 횟수가 너무 적습니다. 레이싱 횟수는 1이상이어야 합니다.",
};

const result = (winnerName) => `
          <div>
          <h2>🏆 최종 우승자: <span id="winners">${winnerName}</span> 🏆</h2>
          <div class="d-flex justify-center">
            <button type="button" class="btn btn-cyan" id="restart">다시 시작하기</button>
          </div>
          </div>
`;

const carButtonHandler = () => {
  carNameArray = splitCarName(carNameDom.value);
  carNameArray.map((val) => {
    checkOverFiveError(val);
  });
  applyOverFiveError();
};

const tryButtonHandler = () => {
  tryNumber = tryNumberDom.value;
  if (tryNumber < 1) return alert(Message.countError);
  let car = new Car();
  car.startRacing(tryNumber, carNameArray);
  tryButtonDom.disabled = true;
};

const carButtonEvent = carButtonDom.addEventListener("click", carButtonHandler);
const tryButtonEvent = tryButtonDom.addEventListener("click", tryButtonHandler);

let carNameArray, tryNumber;
let isSmallerFive = true;

const splitCarName = (val) => val.split(",");
const checkOverFiveError = (val) => {
  if (val.length > 5 || val.length < 1) {
    alert(Message.overFiveError);
    isSmallerFive = false;
  }
};
const applyOverFiveError = () => {
  if (isSmallerFive) {
    carButtonDom.disabled = true;
    sectionRaceTimes.hidden = false;
  } else {
    isSmallerFive = true;
  }
};

let isGo = [];

let tryObject = {};

class ReturnInitialize {
  returnToOriginalHandler = () => {
    this.initializeDom();
    this.initializeValue();
    this.initializeAttr();
  };

  initializeDom = () => {
    while (progressTitle.hasChildNodes()) progressTitle.firstChild.remove();
    while (resultDom.hasChildNodes()) resultDom.firstChild.remove();
  };

  initializeValue = () => {
    countArray = {};
    max = -Infinity;
    maxCarName = [];
    $("#inputCarName").value = "";
    $("#inputTryNumber").value = "";
  };

  initializeAttr = () => {
    sectionRaceTimes.hidden = true;
    carButtonDom.disabled = false;
    tryButtonDom.disabled = false;
  };
}

class Compare extends ReturnInitialize {
  constructor() {
    super();
  }
  compareCountAndTryNumber = (tryObject) => {
    if (tryObject.count === Number(tryObject.tryNumber)) {
      clearInterval(tryObject.timer);
      $All(".relative").forEach((x) => x.remove());
      this.checkWinner();
      resultDom.innerHTML = result(maxCarName);
      $All(".btn-cyan")[2].addEventListener(
        "click",
        this.returnToOriginalHandler
      );
      setTimeout(() => {
        alert(Message.success);
      }, 2000);
    }
  };

  checkWinner = () => {
    for (const idx in countArray) {
      if (max < countArray[idx]) {
        maxCarName = [];
        maxCarName.push(idx);
        max = countArray[idx];
      } else if (max === countArray[idx]) {
        maxCarName.push(idx);
        max = countArray[idx];
      }
    }
  };
}

class Timer extends Compare {
  constructor() {
    super();
  }
  timerCheck = (count, carNameArray, tryNumber, carMovingDom) => {
    tryObject.count = count;
    tryObject.tryNumber = tryNumber;
    tryObject.timer = setInterval(() => {
      isGo = carNameArray.map(() =>
        Math.floor(Math.random() * 10) >= 4 ? true : false
      );
      this.goCarMove(carNameArray, isGo, carMovingDom);
      tryObject.count++;
      this.compareCountAndTryNumber(tryObject);
    }, 1000);
  };

  goCarMove = (carNameArray, isGo, carMovingDom) => {
    carNameArray.map((val, idx) => {
      if (countArray[val] !== undefined)
        countArray[val] = isGo[idx] ? ++countArray[val] : countArray[val];
      else countArray[val] = isGo[idx] ? 1 : 0;
      this.addMovingDom(isGo, idx, carMovingDom);
    });
  };

  addMovingDom = (isGo, idx, carMovingDom) => {
    if (isGo[idx]) carMovingDom[idx].insertAdjacentHTML("afterend", moving);
  };
}

class Car extends Timer {
  constructor() {
    super();
  }

  startRacing = (tryNumber, carName) => {
    let count = 0;
    carName.map((val) => (progressTitle.innerHTML += setting(val)));
    const carMovingDom = $All(".car-player");
    this.timerCheck(count, carName, tryNumber, carMovingDom);
  };
}

let maxCarName = [];
let countArray = {};
let max = -Infinity;

class를
ReturnInitialize -> Compare -> Timer -> Car 형태로 나누어 처리한다.

주의할점

class 상속을 처리할때 순서에 주의한다. (아니면 에러가 뜬다.)
부모클래스가 먼저 작성되고 그것을 자식클래스가 이해하고 처리해야한다.
위의 코드도 순서가 ReturnInitialize -> Compare -> Timer -> Car로 작성된다.

자식클래스에서 부모의 상속을 받는다면 constructor로 super() 추가해야한다.

└──  ReturnInitialize ( returnToOriginalHandler, initializeDom,initializeValue, initializeAttr) 
       └──  Compare (compareCountAndTryNumber, checkWinner)
              └──  Timer (timerCheck, goCarMove, addMovingDom)
                     └──  Car (startRacing)

new Car할때 값을 넘기기

기존에 인스턴스.startRacing(매개변수) 대신 new Car(매개변수)를 넣어서 한다.

기존

  let car = new Car();
  car.startRacing(tryNumber, carNameArray);

....


class Car extends Timer {
  constructor() {
    super();
  }

  startRacing = (tryNumber, carName) => {
    let count = 0;
    carName.map((val) => (progressTitle.innerHTML += setting(val)));
    const carMovingDom = $All(".car-player");
    this.timerCheck(count, carName, tryNumber, carMovingDom);
  };
}

수정 : new Car() 에서 new Car(tryNumber, carNameArray)로 처리
this.tryNumber = tryNumber;
this.carName = carName;
코드 추가 필요

  let car = new Car(tryNumber, carNameArray);
  car.startRacing();

....


class Car extends Timer {
  constructor(tryNumber, carName) {
    super();
    this.tryNumber = tryNumber;
    this.carName = carName;
  }

  startRacing = () => {
    let count = 0;
    this.carName.map((val) => (progressTitle.innerHTML += setting(val)));
    const carMovingDom = $All(".car-player");
    this.timerCheck(count, this.carName, tryNumber, carMovingDom);
  };
}
profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자

0개의 댓글