자바스크립트 계산기 만들기 2: 계산기능 구현, 예외처리
계산 기능 구현 산술 연산자는 숫자 값을 피연산자로 받아 하나의 숫자 값을 반환합니다. 표준 산술 연산자는 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/)입니다. - MDN 자바스크립트에서 사칙연산과 관련
kanhi.tistory.com
아래 나오는 코드는 모두 위 블로그 복붙입니다.
이 분의 설명 굉장히 굉장합니다.
위 글은 자바스크립트를 처음 시작하고 계산기 만드는 것에 좌절하고 있던 제게, 한 줄기 빛이 되어주었습니다.
글 쓰신 분께 큰 감사의 말씀을 드립니다.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cal</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<input type="text" disabled>
<div class="button-wrap">
<button data-type="ac" class="ac">AC</button>
<button data-type="operator">÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button data-type="operator">×</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button data-type="operator">-</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button data-type="operator">+</button>
<button class="zero">0</button>
<button>.</button>
<button data-type="equals" class="equals">=</button>
</div>
</main>
<script src="script.js"></script>
</body>
</html>
CSS
/* style.css */
main {
width: 300px;
}
.button-wrap {
display: grid;
/* 한 줄에 4개씩, 모두 동일한 비율 적용(1:1:1:1) */
grid-template-columns: repeat(4, 1fr);
}
.ac {
/* 첫 번째 선부터 4번째 선까지 지정 */
grid-column: 1/4;
}
.zero {
/* 첫 번째 선부터 3번째 선까지 지정 */
grid-column: 1/3;
}
* {
box-sizing: border-box;
color: white;
}
input,
button {
height: 70px;
outline: none;
}
input {
width: 100%;
text-align: right;
border: none;
background: #5B5B5D;
padding-right: 1rem;
font-size: 3rem;
}
button {
background: #828284;
border: 1px solid #454448;
font-size: 2rem;
}
/* nth-child(4n+2): 4번째 요소마다 스타일을 적용하는데 처음에만 두번째에 적용 */
button:nth-child(4n+2),
button:last-child {
background-color: orange;
}
button:hover {
opacity: .5;
}
.ac {
grid-column: 1/4;
background: #6A6A6C;
}
.zero {
grid-column: 1/3;
}
Javascript
class Calculator {
constructor(displayElement) {
this.displayElement = displayElement
this.operatorCheck = true
this.equalsCheck = false
this.clear()
}
appendNumber(number) {
if (this.equalsCheck) {
this.displayContent = number // 마지막에 누른 것이 '=' 라면 새로운 식 입력
this.equalsCheck = false; // = 버튼 클릭 여부 관리
} else {
this.displayContent += number // 마지막에 누른 것이 '=' 가 아니라면 기존 식에 추가
}
this.operatorCheck = false // 숫자 입력시 false
}
appendOperator(operator) {
if (this.operatorCheck) return false
if (this.equalsCheck) this.equalsCheck = false
this.displayContent += operator
return this.operatorCheck = true
}
updateDisplay() {
this.displayElement.value = this.displayContent
}
clear() {
this.displayContent = ''
this.displayElement.value = 0
this.operatorCheck = true
}
compute() {
this.equalsCheck = true
if (this.operatorCheck) return
this.displayContent = eval(this.displayContent
.replace(/\u00D7/gi, '*')
.replace(/\u00F7/gi, '/')
)
}
}
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
buttons.forEach(button => {
button.addEventListener('click', () => {
switch (button.dataset.type) {
case 'operator':
if (calculator.appendOperator(button.innerText)) {
calculator.updateDisplay()
}
break
case 'ac':
calculator.clear()
break
case 'equals':
calculator.compute()
calculator.updateDisplay()
break
default:
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
break
}
})
})
다른 건 차치하고 javascript 이해하는 것이 너무 어려워서
세 시간 동안 계속 머리 터지도록 생각했고, 그것을 토대로 대충 이해한 내용을 적어보겠다.
1. 숫자 3을 입력한다
button.innerText 가 number 기 때문에
appendNumber 로 들어간다
equalsCheck 를 하는데 기본값이 false 기 때문에
displayContent 에 += 3
0 이었던 displayElement.value 에 3 이 다시 할당됨
그리고 다시 맨 밑에 calculator.updateDisplay() 가 실행된다
현재 계산기 안의 값은 3
근데 어떻게 HTML 의 input text 창에
3이 넘어가는 건지는 아직 모르겠음 (js 와 HTML 의 연결고리가 뭘까)
-> 제일 처음에 displayElement 에 input 셀렉터에서 가져온 값을 할당하기 때문이 아닐까 싶긴 함.
정확한 원리는 모르겠음.
// const displayElement = document.querySelector('input') 참고
그리고 operatorCheck 를 false 로 바꾸면서 한 턴 마무리
2. + 를 입력한다
button.innerText 가 operator 기 때문에
appendOperator 로 들어간다
operatorCheck 를 하는데 방금 3을 입력하면서 값이 false 로 바뀌었기 때문에
if 문을 건너뛰고 true 값을 return 한다
그리고 operatorCheck 는 다시 true 로 바뀐다
맨 밑에 case ‘operator’ 에서
if 문 안의 것을 수행한다. // calculator.updateDisplay()
현재 계산기 안의 값은 3+
현재 operatorCheck 는 true
3. 이번엔 - 를 입력해본다
button.innerText 가 operator 기 때문에
appendOperator 로 들어간다
operatorCheck 가 true 이므로 false 값을 리턴한다
맨 밑에 case ‘operator’ 에서
if 문을 건너뛰고 break 걸려 빠져나간다 ( - 라는 기호가 계산기에 입력되지 않음)
4. 숫자 2를 입력한다
button.innerText 가 number 기 때문에
appendNumber 로 들어간다
equalsCheck 를 하는데 기본값이 false 기 때문에
displayContent 에 += 2
맨 밑에 calculator.updateDisplay() 가 실행된다
현재 계산기 안의 값은 3+2
그리고 operatorCheck 를 false 로 바꾸면서 한 턴 마무리
5. = 를 입력한다
button.innerText 가 equals 이기 때문에
calculator.compute() 실행
compute() 가 실행되면서
equalsCheck 가 true 로 바뀜
// 이게 참조한 블로그에 빠져 있었다. 계산이 끝난 뒤 결과값이 계산기에 출력되고 있을 때,
새로운 숫자가 입력되면 초기화가 돼야 정상인데 계속 결과값에 숫자가 추가돼가지고 헤맸음..
operatorCheck 는 false 이므로 return 되지 않고 밑에 있는 명령 실행 (곱셈 기호와 나눗셈 기호를 * / 처럼 생각하고 계산하라)
그리고 맨 밑에 updateDisplay 를 실행하고 종료
현재 계산기 안의 값은 5
현재 equalsCheck true
현재 operatorCheck false
6. 다시 숫자 7을 입력한다
button.innerText 가 operator 기 때문에
appendOperator 로 들어간다
equalsCheck 를 하는데 방금 true 로 바뀌었기 때문에
displayContent 는 += 7 이 아니라 새로 7이 할당됨
그리고 equalsCheck 는 다시 false 로 변경되고
operatorCheck 를 false 로 바꾸면서 턴 종료
현재 계산기 안의 값은 7
현재 operatorCheck false
현재 equalsCheck false
이렇게 계속 진행된다….
6-1. 계산이 끝난 뒤 연산자를 입력할 경우
현재 계산기 안의 값은 5
현재 equalsCheck true
현재 operatorCheck false
+ 를 입력한다
button.innerText 가 operator 기 때문에
appendOperator 로 들어간다
operatorCheck 가 false 이므로 if 문을 건너뛰고
다음 if 문으로 넘어간다
equalsCheck 가 true 이므로 equalsCheck 를 false 로 바꿔준다
*이렇게 하지 않으면 계산이 끝난 뒤에
+ 입력
2 입력하면
5, 5+, 7 이렇게 연산되지 않고
5, 5+, 2 이렇게 리셋된다
마치며...
뭐 이렇게까지 재밌나 싶을 정도로 시간 가는 줄 모르게 재밌다.
더 열심히 해서 이정도는 진짜 그냥 소설책 읽듯이 이해하고 싶다.
마지막으로 다시 한 번 저 블로그의 주인 kanhi 씨께 감사의 말을 전한다.
제일 처음에 displayElement 에 input 셀렉터에서 가져온 값을 할당하기 때문이 아닐까 싶긴 함.
정확한 원리는 모르겠음.
이거 알고싶다...
자바스크립트 계산기 만들기 2: 계산기능 구현, 예외처리
계산 기능 구현 산술 연산자는 숫자 값을 피연산자로 받아 하나의 숫자 값을 반환합니다. 표준 산술 연산자는 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/)입니다. - MDN 자바스크립트에서 사칙연산과 관련
kanhi.tistory.com
'부트캠프 > 따로 공부' 카테고리의 다른 글
font awesome 사용 방법 (0) | 2023.01.20 |
---|---|
Javascript reduce() 메서드 (0) | 2023.01.03 |
오늘의 목표 (0) | 2022.12.22 |
생활코딩 WEB1, NAV BAR (0) | 2022.12.17 |
HTML 1일차 <a><a/>, <img> 태그와 target (0) | 2022.12.16 |