JavaScript Web Game(계산기)

Dev_Go·2022년 7월 14일
0

JavaScript Web Game

목록 보기
2/3
post-thumbnail

계산기 예제보기

순서도 그리기

  1. numOne이 존재해야 operator도 존재가능
  2. operator가 존재해야 numTwo가 존재가능
  3. numTwo가 존재한다는 뜻은 numOne과 operator도 존재한다는 뜻

함수를 반환하는 함수

const func = () => {
  return () => {
    console.log('hello');
  }
}

func 함수를 호출하면 함수를 반환한다. 반환된 함수는 다른 변수에 저장할 수 있고 변수에 저장된 함수를 다시 호출할 수도 있다.

const innerFunc = func();
innerFunc(); // hello

아래 코드는 위 코드를 풀어쓴 코드입니다. 같은 코드입니다.

const = innerFunc = () => {
  console.log('hello');
};
innerFunc(); // hello

함수가 호출된 코드(함수 이름 뒤에 ()가 붙은 코드)가 있다면 그 부분을 실제 return 값으로 치환하면 이해하기 쉽다.

func 함수는 hello라는 문자열을 console.log하는 함수를 찍어내는 공장이라고 생각할 수 있다. func 함수를 호출할 때마다 return한 함수가 생성된다.

const innerFunc1 = func();
const innerFunc2 = func();
const innerFunc3 = func();

hello라는 문자열을 다른 값으로 바꾸고 싶다면 반환하는 값을 지정하지 않고 매개변수를 사용하면 됩니다.

const func = (msg) => {
  return () => {
    console.log(msg);
  }
}

func함수를 호출하면, func함수에 넣은 매개변수를 console.log 하는 함수가 반환된다.

const innerFunc1 = func('hello');
const innerFunc2 = func('javascript');
const innerFunc3 = func();
innerFunc1(); // hello
innerFunc2(); // javascript
innerFunc3(); // undefined

func처럼 함수를 만들어내는 함수를 고차 함수(high order function)라고 한다.

화살표 함수 문법에 따라 함수의 본문에서 바로 return되는 값이 있으면 {와 return을 생략할 수 있다.

const func = (msg) => {
  return () => {
    console.log(msg);
  }
}

// 위와 아래 코드는 같다.

const func = (msg) => () => {
  console.log(msg);
}

이벤트 리스너를 연결하는 코드에서 0 부터 9까지의 숫자를 제외한 나머지 부분이 같기 때문에 고차 함수를 사용해 0 부터 9까지 저장하는 부분은 매개변수로 만들고 다른 부분은 함수로 만들 수 있다.


함수 중복 제거하기

아래 함수는 숫자를 제외하고 똑같은 함수를 10번 반복하고 있다.

    document.querySelector('#num-0').addEventListener('click', () => {
      if (operator) { //비어있지 않다
        numTwo += '0'; // numTwo에 0을 넣는다.
      } else { // 비어있다.
        numOne +='0'; // numOne에 0을 넣는다.
      }
      $result.value += '0';
    });
    document.querySelector('#num-1').addEventListener('click', () => {
      if (operator) { 
        numTwo += '1';
      } else { 
        numOne +='1';
      }
      $result.value += '1';
    });
    document.querySelector('#num-2').addEventListener('click', () => {
      if (operator) { 
        numTwo += '2';
      } else { 
        numOne +='2';
      }
      $result.value += '2';
    });
    document.querySelector('#num-3').addEventListener('click', () => {
      if (operator) { 
        numTwo += '3';
      } else { 
        numOne +='3';
      }
      $result.value += '3';
    });
    document.querySelector('#num-4').addEventListener('click', () => {
      if (operator) { 
        numTwo += '4';
      } else { 
        numOne +='4';
      }
      $result.value += '4';
    });
    document.querySelector('#num-5').addEventListener('click', () => {
      if (operator) { 
        numTwo += '5';
      } else { 
        numOne +='5';
      }
      $result.value += '5';
    });
    document.querySelector('#num-6').addEventListener('click', () => {
      if (operator) { 
        numTwo += '6';
      } else { 
        numOne +='6';
      }
      $result.value += '6';
    });
    document.querySelector('#num-7').addEventListener('click', () => {
      if (operator) { 
        numTwo += '7';
      } else { 
        numOne +='7';
      }
      $result.value += '7';
    });
    document.querySelector('#num-8').addEventListener('click', () => {
      if (operator) { 
        numTwo += '8';
      } else { 
        numOne +='8';
      }
      $result.value += '8';
    });
    document.querySelector('#num-9').addEventListener('click', () => {
      if (operator) { 
        numTwo += '9';
      } else { 
        numOne +='9';
      }
      $result.value += '9';
    });

중복되는 부분을 onClickNumber변수에 넣고 달라져야되는 숫자는 매개변수 number로 넣어줬다.

    let numOne = '';
    let operator = '';
    let numTwo = '';
    const $operator = document.querySelector('#operator');
    const $result = document.querySelector('#result');
    const onClickNumber = (number) => () => {
        if (operator) { //비어있지 않다
        numTwo += number; // numTwo에 숫자를 넣는다.
        } else { // 비어있다.
          numOne += number; // numOne에 숫자를 넣는다.
        }
        $result.value += number;      
    }; // 고차함수 (high order function) : 함수가 함수를 리턴하는 함수

    document.querySelector('#num-0').addEventListener('click', onClickNumber('0'));
    document.querySelector('#num-1').addEventListener('click', onClickNumber('1'));
    document.querySelector('#num-2').addEventListener('click', onClickNumber('2'));
    document.querySelector('#num-3').addEventListener('click', onClickNumber('3'));
    document.querySelector('#num-4').addEventListener('click', onClickNumber('4'));
    document.querySelector('#num-5').addEventListener('click', onClickNumber('5'));
    document.querySelector('#num-6').addEventListener('click', onClickNumber('6'));
    document.querySelector('#num-7').addEventListener('click', onClickNumber('7'));
    document.querySelector('#num-8').addEventListener('click', onClickNumber('8'));
    document.querySelector('#num-9').addEventListener('click', onClickNumber('9'));

고차함수 말고 다른 방법 사용하기

    let numOne = '';
    let operator = '';
    let numTwo = '';
    const $operator = document.querySelector('#operator');
    const $result = document.querySelector('#result');
    const onClickNumber = (event) => {
        if (operator) { //비어있지 않다
          numTwo += event.target.textContent; // numTwo에 숫자를 넣는다.
        } else { // 비어있다.
          numOne += event.target.textContent; // numOne에 숫자를 넣는다.
        }
        $result.value += event.target.textContent;
    };

    document.querySelector('#num-0').addEventListener('click', onClickNumber);
    document.querySelector('#num-1').addEventListener('click', onClickNumber);
    document.querySelector('#num-2').addEventListener('click', onClickNumber);
    document.querySelector('#num-3').addEventListener('click', onClickNumber);
    document.querySelector('#num-4').addEventListener('click', onClickNumber);
    document.querySelector('#num-5').addEventListener('click', onClickNumber);
    document.querySelector('#num-6').addEventListener('click', onClickNumber);
    document.querySelector('#num-7').addEventListener('click', onClickNumber);
    document.querySelector('#num-8').addEventListener('click', onClickNumber);
    document.querySelector('#num-9').addEventListener('click', onClickNumber);

first, second, third가 반환하는 반환값

const hof = (a) => (b) => (c) => {
  return a + (b * c);
};

const first = hof(3);
const second = first(4);
const third = second(5);

consloe.log(third);

first가 반환하는 값

(b) => (c) => {
  return 3 + (b * c);
};

second가 반환하는 값

(c) => {
  return 3 + (4 * c);
};

third가 반환하는 값

  return 3 + (4 * 5);

정답

consloe.log(third); // 23

if 중첩문 줄이기

지금까지 작업한 것을 실행해보면 오류가 생긴다.
numOne을 입력하고 연산자를 입력한 뒤 numTwo를 입력할 때 numOne의 숫자가 사라지지 않는다.

const onClickNumber = (event) => {
  if (operator) { //비어있지 않다
    if (!numTwo) { // numTwo가 없으면 화면에 숫자를 지워라
      $result.value = '';
    }
    numTwo += event.target.textContent; // numTwo에 숫자를 넣는다.
    $result.value += event.target.textContent;
  } else { // 비어있다.
    numOne += event.target.textContent; // numOne에 숫자를 넣는다.
    $result.value += event.target.textContent;
  }      
};
  1. if문 다음에 나오는 공통된 절차를 각 분기점 내부에 넣는다.
  2. 분기점에서 짧은 절차부터 실행하게 if문을 작성한다.
  3. 짧은 절차가 끝나면 return(함수 내부의 경우)이나 break(for문 내부의 경우)로 중단한다.
  4. else를 제거한다.(이때 중첩 하나가 제거된다.)
  5. 다음 중첩된 분기점이 나오면 1~4의 과정을 반복한다.
const onClickNumber = (event) => {
  if (!operator) { //비어있다
    numOne += event.target.textContent; // numOne에 숫자를 넣는다.
    $result.value += event.target.textContent;
    return;
  }
  // 비어있지 않다.
  if (!numTwo) { // numTwo가 없으면 화면에 숫자를 지워라
    $result.value = '';
  }
  numTwo += event.target.textContent; // numTwo에 숫자를 넣는다.
  $result.value += event.target.textContent;
};

if 중첩문 줄이기 예제

줄이기 전

function test() {
  let result = '';
  if (a) {
    if (!b) {
      result - 'c';
    }
  } else {
    result = 'a';
  }
  result += 'b';
  return result;
}

줄인 후

function test() {
  let result = '';
  if (!a) {
    result = 'a';
    result += 'b';
    return result;
  }
  if (!b) {
      result - 'c';
    }
    result += 'b';
    return result;
}

switch문을 if문으로 바꾸기

switch문

document.querySelector('#calculate').addEventListener('click', () => {
  if (numTwo) {
    switch (operator) {
      case '+':
        $result.value = parseInt(numOne) + parseInt(numTwo);
        break;
      case '-':
        $result.value = numOne - numTwo;
        break;
      case '*':
        $result.value = numOne * numTwo;
        break;
      case '/':
        $result.value = numOne / numTwo;
        break;
      default:
        break;
    }
  } else {
    alert('숫자를 먼저 입력하세요.')
  }
});

if문

document.querySelector('#calculate').addEventListener('click', () => {
  if (numTwo) {
    if (operator === '+') {
      $result.value = parseInt(numOne) + parseInt(numTwo);
    } else if (operator === '-') {
      $result.value = numOne - numTwo;
    } else if (operator === '*') {
      $result.value = numOne * numTwo;
    } else if (operator === '/') {
      $result.value = numOne / numTwo;
    }
  } else {
    alert('숫자를 먼저 입력하세요.')
  }
});

초기화

C버튼 누르면 초기화된다.

document.querySelector('#clear').addEventListener('click', () => {
  numOne = '';
  operator = '';
  numTwo = '';
  $operator.value = '';
  $result.value = '';
});
profile
프론트엔드 4년차

0개의 댓글