Javascript

Javascript 계산기 만들기

개굴이 dev 2020. 5. 10. 18:16

🔢 자바스크립트로 계산기 만들기

eval() 함수를 이용하여 계산기를 만듭니다.

난이도 ⭐
예제 Retro Calculator with JS

 

기능 정의

  1. 버튼 클릭 > 클릭 이벤트가 발생한 값 저장
    • 숫자
    • 연산 +, -, /, *
    • 양수/음수 +/-
    • 소수점 .
  2. = 버튼 클릭
  3. 저장된 값들을 연산
  4. 연산된 값들을 출력
  5. A/C 버튼은 현재 값과 저장된 값 모두 삭제, C 버튼은 현재 입력된 값만 삭제하는 기능

 

기본 구조

클릭한 값들이 보여질 공간과 숫자,연산 버튼이 있는 공간으로 나눠집니다.

 

테이블 태그를 사용하는 방법도 있지만 모던 웹 방식에 맞추어 flexbox로 레이아웃을 설계했습니다.

기능이 같은 버튼들은 공통 클래스명을 줍니다.

<div class="viewer">
	<button class="btn all-clear">AC</button>
	<button class="btn clear">C</button>
	<button class="btn sign">+/-</button>
	<button class="btn symbol divide">/</button>
	<button class="btn num">7</button>
	<button class="btn num">8</button>
	<button class="btn num">9</button>
	<button class="btn symbol times">*</button>
	<button class="btn num">4</button>
	<button class="btn num">5</button>
	<button class="btn num">6</button>
	<button class="btn symbol minus">-</button>
	<button class="btn num">1</button>
	<button class="btn num">2</button>
	<button class="btn num">3</button>
	<button class="btn symbol plus">+</button>
	<button class="btn num">0</button>
	<button class="btn dot">.</button>
	<button class="btn equal">=</button>
</div>

 

스타일링은 window 계산기 버전, 아이폰 버전 등 원하는 느낌으로 하시면 됩니다.

 

Step 1. 공통 변수 선언

모든 클릭 이벤트에 사용될 변수입니다. currentValue는 숫자든 연산 부호든 내가 클릭하는 값을 담습니다.
store는 클릭한 것들이 계속 담겨집니다. A/C버튼을 누르지 않는 한 사라지지 않습니다.

const currentValue = document.querySelector('.current-value');
const store  = document.querySelector('.store');

 

Step 2. 숫자 버튼 클릭

숫자 버튼을 클릭하고 값을 볼 수 있도록 처리해 봅니다.
배열 메소드(map)를 사용하기 위해 숫자 버튼의 유사배열을 진짜 배열에 담아 주고, number를 클릭할 때 작동할 setNum 함수를 작성합니다.

const numbers = Array.from(document.querySelectorAll('.num'));

numbers.map(number => {
  number.addEventListener('click', setNum);
})

function setNum() {
  currentValue.innerText += this.innerText;
}

 

Array.from() : 유사배열을 진짜 배열로 바꿔 줍니다.

 

Step 3. 연산 버튼 클릭

숫자 버튼처럼 배열메소드 안에 클릭 이벤트를 작성해 줍니다. 클리어 함수는 간단하므로 마지막 순서에 다뤄 보겠습니다.

const symbols = Array.from(document.querySelectorAll('.symbol'));

symbols.map(symbol => {
  symbol.addEventListener('click', setSymbol);
})

function setSymbol() { 
  if (currentValue.innerText !== '') { //현재 값에 아무도 없다면
    if (store.innerText === '') { // 첫 입력이라면
      store.innerText = currentValue.innerText + ' ' + this.innerText
    } else { // 첫 입력이 아닐 경우
      store.innerText = `${store.innerText} ${currentValue.innerText} ${this.innerText}`
    }
  } 
  
  clearValue(); 
}

우선 연산까지만 하고 계산 결과값을 구해 보겠습니다.

 

Step 4. = 버튼 클릭하여 결과값 구하기

자바스크립트는 데이터를 string으로 저장합니다. string 타입의 값들끼리 계산해 주기 위해 eval() 함수를 사용했습니다.
이제 숫자끼리 더하거나 빼보시면 결과값을 확인할 수 있습니다.

const equal = document.querySelector('.equal');

equal.addEventListener('click', getTotal);

function getTotal() {
  if(currentValue.innerText !== '') { 
    currentValue.innerText = eval(store.innerText + currentValue.innerText);
  } 
  clearStore();
}

 

eval(string)
그러나 eval() 은 보안 이슈가 있기에 지양해야 합니다. 다음에는 eval() 함수 없이 계산기 만들기도 올리겠습니다.

 

Step 5. +/- 와 . 클릭

코드 길이를 줄이기 위해 if문 말고 삼항연산자를 사용했습니다.

const dot = document.querySelector('.dot');
const sign = document.querySelector('.sign');

dot.addEventListener('click', setDot);

sign.addEventListener('click', setSign);

function setDot() {
  currentValue.innerText.indexOf('.') === -1 ? 
  currentValue.innerText = `${currentValue.innerText}.` :
  false;
}

function setSign() {
  currentValue.innerText.indexOf('-') === -1 ? 
  currentValue.innerText = `-${currentValue.innerText}` :
  currentValue.innerText = currentValue.innerText.replace('-','');
}

 

Step 6. 마지막 Clear 함수!

클리어 버튼만 클릭하면 현재 값만 지워줍니다. AC(all clear) 버튼은 현재값, 저장된 값 모두 삭제하여 초기화 상태로 만듭니다.

const clear = document.querySelector('.clear');
const allClear = document.querySelector('.all-clear');

clear.addEventListener('click', clearValue);

allClear.addEventListener('click', function(){
  clearValue();
  clearStore();
});

function clearValue() {
  currentValue.innerText = '';
}

function clearStore() {
  store.innerText = '';
}

 

Step 7. 추가적으로 하면 좋은 것

6번째까지 하시면 계산기는 완성입니다. 하지만 좀 더 디테일을 위해 추가하면 좋은 내용이 있습니다.

고정 너비로 되어 있기 때문에 숫자 갯수가 증가하면 디자인을 벗어납니다.

 

그래서 setNum() 함수에 length 제한을 두면 더 좋겠죠?
25자가 넘어가면 알럿이 뜨도록 작성했습니다.

function setNum() {
  currentValue.innerText.length < 25 ? 
  currentValue.innerText += this.innerText :
  alert('Oooops🤦 Can you re-enter it within the maximum input range?');
}