-
자바스크립트 계산기 만들기 2: 계산기능 구현, 예외처리자바스크립트 2020. 4. 10. 08:26
계산 기능 구현
산술 연산자는 숫자 값을 피연산자로 받아 하나의 숫자 값을 반환합니다.
표준 산술 연산자는 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/)입니다. - MDN자바스크립트에서 사칙연산과 관련된 산술 연산자는 +, -, *, /이다.
10 + 2 // 12 10 - 2 // 8 10 * 2 // 20 10 / 2 //5
자바스크립트의 eval 함수를 사용하면 계산 기능을 쉽게 구현할 수 있다.
eval()은 문자로 표현된 JavaScript 코드를 실행하는 함수이다.
간단한 예로 a 변수에 2 + 3 * 5 연산식을 저장하고 eval 함수에 인자로 a를 넣고 실행하면 식이 계산된다.
let a = '2 + 3 * 5' eval(a) // 17
그럼 계속해서 클래스에 compute 메서드를 추가하고 eval() 함수를 사용해서 계산 기능 구현
class Calculator { //... compute() { this.displayContent = eval(this.displayContent) } }
= 버튼 클릭 시 compute 메서드를 호출하도록 연결
buttons.forEach(button => { button.addEventListener('click', () => { switch (button.dataset.type) { // ... case 'equals': calculator.compute() calculator.updateDisplay() break default: calculator.appendNumber(button.innerText) calculator.updateDisplay() break } }) })
더하기와 빼기는 잘 되지만 곱하기와 나누기는 에러가 발생. 자바스크립트에서는 곱하기와 나누기가 ×, ÷가 아닌 *, / 를 사용하므로
replace를 사용하여 × -> *로, ÷ -> / 로 변경해준 후 계산
class Calculator { // ... compute() { this.displayContent = eval(this.displayContent .replace('\u00D7', '*') .replace('\u00F7', '/') ) } }
예외 처리
큰 기능들은 완성했지만 아직 문제가 많다
• 2++3처럼 연산자를 연속으로 입력할 수 있다.
• ÷3 처럼 숫자보다 연산자가 먼저 입력이 가능하다.
• 6X 처럼 식이 완전하지 않은 상태에서 = 버튼을 클릭하면 에러가 발생한다.
• 2+3 = 5로 계산이 끝난 뒤 새로운 계산을 하기 위해 3을 입력하면 53으로 표시된다.첫 번째 문제부터 하나씩 고쳐 가보자
2+ 를 입력하고 다시 연산자를 선택하면 입력되는 걸 막기 위해
연산자 선택 여부를 관리하는 operatorCheck 속성을 추가
class Calculator { constructor(displayElement) { this.displayElement = displayElement this.operatorCheck = false // 연산자 선택 여부 저장 this.clear() } appendNumber(number) { this.displayContent += number this.operatorCheck = false // 숫자 입력 시 false } appendOperator(operator) { if (this.operatorCheck) return // operatorCheck값이 true이면 함수 빠져나가기 this.displayContent += operator this.operatorCheck = true // 연산자 입력 시 true } }
appendOperator 메서드 호출 시 this.operatorCheck가 true이면 (이미 연산자를 입력한 상태이면) this.displayContent에 연산자를 추가하지 않고 빠져나감
숫자를 입력한 뒤에는 다시 연산자를 입력할 수 있게 this.operatorCheck를 false로 변경
그다음, ÷3 처럼 숫자 입력 전 연산자가 입력되는 걸 막기 위해 this.operatorCheck 초기값을 true로 변경
class Calculator { constructor(displayElement) { this.displayElement = displayElement this.operatorCheck = true // false -> true this.clear() } //... appendOperator(operator) { if (this.operatorCheck) return this.displayContent += operator this.operatorCheck = true } } // ... buttons.forEach(button => { button.addEventListener('click', () => { switch (button.dataset.type) { case 'operator': calculator.appendOperator(button.innerText) calculator.updateDisplay() break } }) })
초기값이 true이기에 숫자 입력 전에 연산자를 클릭하면 연산자가 this.displayContent에 추가되지 않고 빠져나간다.
다만, 빠져나가는 거와는 상관없이 this.updateDisplay()가 실행되기 때문에 appendOperator가 true를 리턴할 때만 업데이트되도록 수정한다.
class Calculator { constructor(displayElement) { this.displayElement = displayElement this.operatorCheck = true this.clear() } //... appendOperator(operator) { if (this.operatorCheck) return false this.displayContent += operator return this.operatorCheck = true } } // ... buttons.forEach(button => { button.addEventListener('click', () => { switch (button.dataset.type) { case 'operator': if (calculator.appendOperator(button.innerText)) { calculator.updateDisplay() } break } }) })
이렇게 하면 연산자가 먼저 입력되지는 않지만 숫자를 입력 -> AC 버튼 클릭 -> 연산자를 선택해보면 여전히 입력이 가능하다
clear 메서드에 this.operatorCheck = true를 추가해 연산자가 입력되지 않도록 막는다.
class Calculator { //... clear() { this.displayContent = '' this.displayElement.value = 0 this.operatorCheck = true } }
6X 를 입력 후 = 버튼을 클릭하면 잘못된 식이기 때문에 에러가 발생한다.
연산자가 마지막으로 입력된 상태일 경우 = 버튼을 클릭해도 eval() 함수가 동작되지 않도록 코드를 수정한다.
class Calculator { //... compute() { if (this.operatorCheck) return // 추가 this.displayContent = eval(this.displayContent .replace('\u00D7', '*') .replace('\u00F7', '/') ) } }
2+3 = 5로 계산을 끝낸 뒤 숫자를 입력하면 전에 계산되었던 결과에 입력한 숫자가 이어져 나타나고 있다.
= 버튼을 클릭 후 숫자를 클릭한다면 AC기능과 비슷하게 새로운 식 입력을 시작하는거니
appendNumber 메서드에서 this.displayContent += number로 숫자가 추가되던걸
= 버튼을 클릭 후 처음으로 숫자를 클릭할 때만 this.displayContent = number로 바로 초기화되게 한다.
= 버튼을 클릭했는지 알아내기 위해 operatorCheck처럼 equalsCheck 속성을 하나 추가해 = 버튼 클릭 여부를 관리한다
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 } }
이제 = 버튼 클릭 후 숫자를 입력하면 이전 결과에 숫자가 이어져 나오지 않고 잘 동작되지만
= 버튼 클릭 -> 연산자 클릭 -> 숫자를 클릭하면 이상하게 입력되고 있다.
2 + 3 계산 후 5 + 2를 입력하고 싶었는데 + 를 클릭 후 2를 선택하니 입력 중이던 식이 사라지고 2만 나타나버렸다
class Calculator { //... appendOperator(operator) { if (this.operatorCheck) return false if (this.equalsCheck) this.equalsCheck = false // 추가 this.displayContent += operator return this.operatorCheck = true } }
appendOperator 메서드에도 equalsCheck가 true일 경우 false로 바꿔주는 코드를 추가한다
아직 많이 부족하고 완벽한 계산기는 아니지만 이 정도면 만족한다.
'자바스크립트' 카테고리의 다른 글
자바스크립트 계산기 만들기 1: 계산기 꾸미기, 계산식 입력 (6) 2020.03.30