코딩하는라민

렛츠기릿 자바스크립트 #6 계산기 만들기 - 함수 사용하기 본문

Core/JavaScript

렛츠기릿 자바스크립트 #6 계산기 만들기 - 함수 사용하기

코딩하는라민 2022. 11. 24. 12:05
728x90
반응형

렛츠기릿 자바스크립트 #6 계산기 만들기 - 함수 사용하기

책 + 저자 유튜브 강의(인프런) + 추가로 모르는 내용들 필기 추가하면서 공부

 

 


 

 

 


 

 

1. 순서도 그리기

① 숫자1, 2 / 연산자 를 저장할 변수를 각각 생성

② 숫자를 누르면 연산자가 입력된 유무에 따라서 숫자1에 저장할지, 숫자2에 저장할지 결정하고 변수에 숫자 저장

③ 연산자 버튼을 누르면 숫자1의 유무에 따라 연산자를 저장하거나 경고창을 띄운다

④ = 버튼을 누르면 숫자2의 유무에 따라 연산자를 결과에 출력하거나 경고창을 띄운다

 

기본원리

- 숫자1이 존재해야 연산자가 존재 가능하고, 연산자가 존재해야 숫자2가 존재 가능하다.

 

 

 

2. 변수 생성하고 버튼에 이벤트리스너 달기

① 변수 생성

let numOne='';
let numTwo='';
let operator='';

- 비어있는 변수 생성

 

 

② 버튼에 이벤트리스너 달기

document.querySelector('#num-0').addEventListener('click', ()=>{})
document.querySelector('#num-1').addEventListener('click', ()=>{})
document.querySelector('#num-2').addEventListener('click', ()=>{})
document.querySelector('#num-3').addEventListener('click', ()=>{})
document.querySelector('#num-4').addEventListener('click', ()=>{})
document.querySelector('#num-5').addEventListener('click', ()=>{})
document.querySelector('#num-6').addEventListener('click', ()=>{})
document.querySelector('#num-7').addEventListener('click', ()=>{})
document.querySelector('#num-8').addEventListener('click', ()=>{})
document.querySelector('#num-9').addEventListener('click', ()=>{})
document.querySelector('#plus').addEventListener('click', ()=>{})
document.querySelector('#minus').addEventListener('click', ()=>{})
document.querySelector('#divide').addEventListener('click', ()=>{})
document.querySelector('#multiply').addEventListener('click', ()=>{})

- 각 버튼을 눌렀을 때 함수가 실행되도록 이벤트리스너르 ㄹ달아준다.

 

 

 고차함수

- 함수는 호출하면 숫자, 문자열, 불값 등을 변환한다.

 

고차함수 (Higher order function)
 : 함수를 파라미터로 전달받거나,  함수를 연산의 결과로 반환해주는 메서드

const func = () => {
       return () => {
              console.log('hello ramin!');
       }
}   // func 를 호출하면 안에 있는 함수를 리턴한다.

내장고차함수(배열에 한함)
 - .filter : 배열의 요소 중에서 특정 조건을 만족하는 요소들만을 걸러내는(filter) 메서드
 - .map : 배열의 요소를 일괄적으로 변경하는데 효과적
 - .reduce : 호출하는 배열의 각각의 멤버에 대해서 콜백 함수를 실행하고 하나의 결과 값만 내보냄

 

3. 버튼을 눌렀을 때 실행할 함수 지정해주기

① 숫자 버튼

const $operator = document.querySelector('#operator');
const $result = document.querySelector('#result');

const onClickNumber = (number) => () => {
  if(operator){
      if(!numTwo){
             $result.value='';
      }
     numTwo += event.target.textContent;
  } else{
     numOne += event.target.textContent;
  }
  $result.value += event.target.textContent;
}

document.querySelector('#num-0').addEventListener('click', onClickNumber)
document.querySelector('#num-1').addEventListener('click', onClickNumber)
...

- 연산자가 있으면 숫자2에 누른 버튼의 숫자를 더하고, 연산자가 없으면 숫자1에 버튼의 숫자를 더한다.

- 그리고 그 결과를 화면에 띄운다.

- 각 이벤트 리스너 연결하여 버튼을 눌러을 때 해당 함수가 실행되도록 해준다.

 

if(!numTwo){
     $result.value='';
}

- operator 가 있는 상태에서 / 숫자키를 누르면 / 숫자2가 없을 때 결과창을 비워줘야 숫자2가 숫자1 옆에 붙지 않고 연산을 제대로 진행할 수 있다.

 

const onClickNumber = (event) => {
      if(!operator){         
         numOne += event.target.textContent;
         $result.value += event.target.textContent;
         return;
      }
	  // 아래부터는 operator 가 있는 경우
      if(!numTwo){
         $result.value='';
      }
      numTwo += event.target.textContent;
      $result.value += event.target.textContent;            
   }

- if문의 중복 제거 : if문 다음에 나오는 공통부분을 안쪽에 각각 넣기 > 짧은 문장을 맨 위로 올려준다 > else 제거 > 반복

- 맨 위에 있는 절차의 끝에는 return을 넣어준다.

 

 

연산자 부분

const onClickOperator = (op) => () => {
      if(numOne){
         operator = op;
         $operator.value = op;
      } else{
         alert('숫자가 없습니다. 숫자 먼저 입력해주세요.');
      }
   }

document.querySelector('#plus').addEventListener('click', onClickOperator('+'));
document.querySelector('#minus').addEventListener('click', onClickOperator('-'));
document.querySelector('#divide').addEventListener('click', onClickOperator('/'));
document.querySelector('#multiply').addEventListener('click', onClickOperator('*'));

- 함수 부분은 고차함수로 하지 않으면 버튼을 클릭했을 때 함수가 제대로 실행되지 않는다.

- 연산자를 눌렀을 때 숫자1이 있다면 연산자가 화면에 표시되고, 숫자1이 없다면 경고창을 띄운다.

 

 

계산하기 버튼

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;         
     }
  } else {
         alert('잘못된 연산입니다.');
      }
});

- 계산하기 버튼을 눌렀을 때 숫자2가 있다면 누른 연산자에 해당하는 연산 결과가 실행되고, 숫자2가 없으면 경고창을 띄운다.

- parseInt () : +는 문자열을 연결해주는 역할이다.

  → 예를들면 12+34 는 46이 아니라 1234이다.

  →  따라서 parseInt는 문자열을 숫자로 바꿔준다.

  →  + 를 제외한 연산자는 문자열을 숫자로 바꿔주고 나서 연산을 실행한다.

  →  즉, + 연산을 할 경우에는 parseInt 를 써준다.

 

리셋 버튼

document.querySelector('#reset').addEventListener('click', ()=>{
  numOne='';
  numTwo='';
  operator='';
  $operator.value='';
  $result.value='';      
});

- 리셋 버튼을 누르면 변수를 초기화하고, input 에 띄워진 값도 처음으로 되돌려준다.

 

 

 


 

 

4. 연산 가능 개수 늘리기 → 혼자 생각해보기

- 계산기는 2자리의 연산만 하는 것이 아니라 여러 가지 숫자의 사칙연산을 할 수 있어야 한다.

- 따라서 계산기가 작동하는 원리를 생각해보는 시간이 되었다.

 

[ 정답 ]

...

const onClickOperator = (op) => () => {
      ...
      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;         
         }
         numOne = $result.value;
         numTwo ='';
      }
} 
   
...

- 연산자 버튼을 눌렀는데 숫자2가 있는 상태이면,

- numOne 에 $result.value 값을 대입 : 숫자1은 결과값이 되고, 숫자2는 초기화된다.

- 예를 들어서 1+2+3을 계산한다고 하면, 1+2를 계산해 3이 되고, 그 다음에 3과 3을 더해 6이라는 결과가 나오는 원리이다. 따라서, 1+2 를 숫자1에 저장하고, 3을 숫자2에 저장해 숫자1 + 숫자2 의 결괏값을 만드는 것.

 

parseInt
: 문자열 인자를 파싱하여 특정 진수의 정수를 반환

Number.parseInt(string)
Number.parseInt(string, radix)

- string : 파싱할 값. 문자열이 아닐 경우에는 toString 연산을 통해 문자열로 변경
- radix : 진수를 나타내는 2부터 36까지의 정수.
             문자를 숫자로 변환할 수 없는 경우나, 진수를 잘못 입력한 경우는 NaN 값이 나온다.

 

eval()
eval 함수를 이용하면 parseInt 함수를 쓰지 않아도 된다.
하지만 이 함수를 이용하면 해커가 입력한 코드를 사용할 수 있기 때문에 ** 보안상 이유로 eval 은 쓰지 않는다.

 

 

완성된 모습

 

 

 

 

 

5. +나 -로 시작하는 숫자의 연산 → 혼자 생각해보기

const onClickOperator = (op) => () => { 
      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;         
         }
         numOne = $result.value;
         numTwo ='';
      }

      if(numOne){
         operator = op;
         $operator.value = op;
      } else if(operator==='-'||'+'){         
         operator = op;
         $operator.value = op;
      } else{
         alert('숫자가 없습니다. 숫자 먼저 입력해주세요.');
      }
   }

- if문 안에 else if 문을 추가해준다.

- else if 문의 조건문에는 연산자가 - 또는 + 으로 해준다.

 

▶ 논리연산자
  ①   ||  
     - or (엔터 위, 원표시 위에 문자)
     - 둘 중 하나만 참(true)이어도 참(true)

  ②   &&    
    - and
    - 둘 다 참(true)이어야 참(true)
    - 하나만 참(true)이거나 둘 다 거짓(false)이면 거짓(false)

 

 

① 오류_함수의 순서

- 그런데 else if문을 추가해준 if(numOne) 의 순서가 앞에서 추가해준 if(numTwo) 보다 아래에 있어야 정상적으로 작동된다.

- 아래의 코드와 같이 순서가 된다면, 연산자를 누르고 숫자를 누르면 NaN 이라고 결과창에 뜨면서 연산을 마친 후 계산하기 버튼을 눌러도 NaN 이라는 결과가 뜬다.

const onClickOperator = (op) => () => { 
      if(numOne){
         operator = op;
         $operator.value = op;
      } else if(operator==='-'||'+'){         
         operator = op;
         $operator.value = op;
      } else{
         alert('숫자 먼저 입력해주세요!!');
      }
      
      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;         
         }
         numOne = $result.value;
         numTwo ='';
      }
   }

 

 

 


 

 

728x90
반응형