자바스크립트 연습 겸 하여 사칙연산 계산기를 만들어보았다. 처음에는 간단할 거라 생각했지만 생각보다 고려해야할 점이 많았다.
복잡한 계산은 아니지만 사칙연산 기능은 문제없이 작동된다.
버튼을 이렇게 일일이 만드는 방법 뿐인가 고민을 했지만 당장 생각나는 방안이 없어 그냥 16개의 버튼을 다 만들었다. 연산자는
operator
, 숫자는numBtn
, 초기화는ac
, 결과는result
라는 클래스를 각각 달아주어 조작했다.<body> <div class='wrap'> <div class='display'> <div class='input'></div> </div> <div class='buttons'> <button data-type="ac" class='ac'>C</button> <button data-type='operator' class='operator'>+</button> <button data-type='operator' class='operator'>-</button> <button data-type='operator' class='operator'>x</button> <button class='numBtn'>7</button> <button class='numBtn'>8</button> <button class='numBtn'>9</button> <button data-type='operator' class='operator'>/</button> <button class='numBtn'>4</button> <button class='numBtn'>5</button> <button class='numBtn'>6</button> <button data-type='result' class='result'>=</button> <button class='numBtn'>1</button> <button class='numBtn'>2</button> <button class='numBtn'>3</button> <button class='numBtn'>0</button> </div> </div> </body>
이유는 모르겠는데 다른 계산기를 만든 분들이 아이폰 기본 계산기의 색감을 따르고 있길래 나도 그렇게 만들어보았다. 사실 디자인적으로 큰 고민은 하지 않은 것 같😅
.wrap { margin: 100px auto; width: 300px; height: 400px; border: 1px solid transparent; background-color: rgb(151, 151, 151); border-radius: 5px; } .input { height: 20px; text-align: right; } .display { display: flex; flex-direction: column; height: 50px; font-size: 36px; font-weight: 700; border: 1px solid #777676; margin: 5px 5px 0 5px; padding: 10px; border-radius: 5px; background-color: #777676; color: #fff; } .buttons { padding: 5px; display: grid; height: calc(100% - 85px); gap: 5px; grid-template-columns: repeat(4, 1fr); } button { color: #fff; font-size: 36px; border: none; border-radius: 5px; cursor: pointer; } .numBtn { background-color: #828284; } .operator, .result, .ac { background-color: orange; }
- 기본적인 계산 기능은
calculate
함수를 만들었다.switch
문을 이용하여 각 연산자 버튼을 눌렀을 때 인자로 받은 첫번째 수와 두번째 수를 계산해준다.operatorOn
,previoustNum
,resentNum
은 각각 연산자를 입력했는지, 이전값인지 직전값인지 판별해주는 변수이다. (연속해서 계속 계산할 수 있도록 연산자를 누른 순간 방금까지 display에 있던 숫자가 previousNum이 된다)const buttons = document.querySelectorAll('button'); const operators = document.querySelectorAll('.operator'); const displayElement = document.querySelector('.input'); const numBtn = document.querySelectorAll('.numBtn'); let operatorOn = ''; // 연산자 입력 let previousNum = ''; //이전 값 let resentNum = ''; // 최근값 //calculate 함수 (previousNum, operatorOn, resentNum 인자로 받음) let calculate = (n1, operator, n2) => { let result = 0; switch (operator) { case '+': result = Number(n1) + Number(n2); break; case '-': result = Number(n1) - Number(n2); break; case 'x': result = Number(n1) * Number(n2); break; case '/': result = Number(n1) / Number(n2); break; default: break; } return String(result); };
- 첫번째 자리에 0이 오면 안되기 때문에
isFirstDigit
변수를 만들어 판별한다. 023 이런거 안되게...- 클릭한 버튼의 클래스를
action
이라는 변수로 두어 어떤 버튼을 클릭했는지 판별한다.- 그 이후에는 각각의 상황에 따라 조건을 부여하여 계산한다. 자세한 조건은 코드 내 주석 참고
let calculator = () => { let isFirstDigit = true; // 첫 번째 숫자 여부를 판별하는 변수 buttons.forEach((item) => { item.addEventListener('click', (e) => { let action = e.target.classList[0]; let click = e.target.innerHTML; if (action === 'operator') { //연산자 눌렀을 때 operatorOn = click; previousNum = displayElement.textContent; displayElement.textContent = ''; isFirstDigit = true; // 연산자를 누르면 다음 숫자는 첫 번째 숫자가 됨 } if (action === 'numBtn') { if (isFirstDigit && click === '0') { // 첫 번째 숫자이고 입력된 값이 0인 경우 아무 작업도 수행하지 않음 return; } if (displayElement.textContent === '' && operatorOn === '') { //창이비어있고 연산자 누르지 않았을때(한자리) displayElement.textContent = click; previousNum = displayElement.textContent; } else if ( //창이비어지 않고 연산자 누르지 않았을때(한자리이상) displayElement.textContent !== '' && operatorOn === '' ) { displayElement.textContent = displayElement.textContent + click; previousNum = displayElement.textContent; } else if ( //창이비어있고 연산자 눌렀을때(한자리) displayElement.textContent === '' && operatorOn !== '' ) { displayElement.textContent = click; resentNum = displayElement.textContent; } else if ( //창이비어있지않고 연산자 누르지 않았을때 (한자리이상) displayElement.textContent !== '' && operatorOn !== '' ) { displayElement.textContent = displayElement.textContent + click; resentNum = displayElement.textContent; } isFirstDigit = false; // 첫 번째 숫자 입력 후에는 첫 번째 숫자가 아님을 표시 } if (action === 'result') { // = 눌렀을 때 calculate함수 실행 displayElement.textContent = calculate( previousNum, operatorOn, resentNum ); isFirstDigit = true; // 결과를 표시한 후에는 다음 숫자는 첫 번째 숫자가 됨 } if (action === 'ac') { //C 버튼 눌렀을 때 모든 할당 초기화 displayElement.textContent = ''; previousNum = ''; operatorOn = ''; resentNum = ''; isFirstDigit = true; // 모든 할당 초기화 후에는 다음 숫자는 첫 번째 숫자가 됨 } }); }); }; calculator();
displayElement.textContent
를 일일이 입력하는게 너무 지저분해보여서 변수로 할당하고 싶었는데 변수에 넣으면 값이 바뀌지 않는다.. 이를 해결하기 위해 찾아보니 따로 displayElement.textContent
를 해주는 함수를 만들라고 하는데 그럼 쓸 때 마다 그 함수를 호출하나 저걸 쓰나 거기서거기 아닌가..? 하는 생각이 들어 보류중이다.function a(value) {
let content = displayElement.textContent
content = value
return content
}
이런식이나
const getDisplayValue = () => displayElement.textContent;
이런식으로 해보라는 조언을 받았는데 이렇게 해서 함수로 쓰면 정말 코드가 덜 지저분해지는게 맞나요..? 아직 잘 모르겠다ㅠ
뭔가 다른 분들은 더 기깔나게 만든 사람이 많은 것 같아 아직도 갈 길이 멀다는 생각이 든다. 하지만 하나의 어플리케이션 결과물을 만든 것도 오랜만이기에 블로그에 글을 써보았다. 다음엔 또 어떤 걸 만들까? 무언가 만들면서 공부하는게 제일 재밌는 것 같다..~