“未捕获的类型错误:单击数字按钮时无法读取未定义的属性(读取‘toString’)
2021-09-04
15801
class Calculator {
constructor(previousOperandTextElement, currentOperandTextElement) {
this.previousOperandTextElement = previousOperandTextElement
this.currentOperandTextElement = currentOperandTextElement
this.clear()
}
clear() {
this.previousOperandTextElement = ''
this.currentOperandTextElement = ''
this.operation = undefined
}
delete() {
}
appendNumber(number) {
this.currentOperand = this.currentOperand.toString() + number.toString()
}
chooseOperator(operation) {
}
compute() {
}
updateDisplay() {
this.currentOperandTextElement.innerHTML = this.currentOperand
}
}
const numberButtons = document.querySelectorAll('[data-number]')
const operationButtons = document.querySelectorAll('[data-operation]')
const equalsButton = document.querySelector('[data-equals]')
const deleteButton = document.querySelector('[data-delete]')
const allClearButton = document.querySelector('[data-all-clear]')
const previousOperandTextElement = document.querySelector('[data-previous-operand]')
const currentOperandTextElement = document.querySelector('[data-current-operand]')
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement)
numberButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.appendNumber(button.innerHTML)
calculator.updateDisplay()
})
})
*,
*::before,
*::after {
box-sizing: border-box;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
font-weight: normal;
}
body {
padding: 0;
margin: 0;
background: linear-gradient(to right, #00AAFF, #00FF6C);
}
.calculator-grid {
display: grid;
justify-content: center;
align-content: center;
min-height: 100vh;
grid-template-columns: repeat(4, 100px);
grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}
.calculator-grid button {
cursor: pointer;
font-size: 2rem;
border: 1px solid white;
outline: none;
background-color: rgba(255, 255, 255, .75);
}
.calculator-grid button:hover {
background-color: rgba(255, 255, 255, .9);
}
.span-two {
grid-column: span 2;
}
.output {
grid-column: 1 / -1;
background-color: rgba(0, 0, 0, 0.75);
border: solid 5px green;
display: flex;
align-items: flex-end;
flex-direction: column;
justify-content: space-between;
padding: 15px;
}
.output .previous-operand {
color: rgba(255, 255, 255, .75);
font-size: 1.5rem;
}
.output .current-operand {
color: rgba(255, 255, 255, .75);
font-size: 2.5rem;
}
<!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>Calculator</title>
<link rel="stylesheet" href="calculator.css">
<script src="calculator.js" defer></script>
</head>
<body>
<div class="calculator-grid">
<div class="output">
<div data-previous-operand class="previous-operand"></div>
<div data-current-operand class="current-operand"></div>
</div>
<button data-all-clear class="span-two">AC</button>
<button data-delete>DEL</button>
<button data-operation>÷</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operation>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operation>+</button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operation>-</button>
<button data-number>.</button>
<button data-number>0</button>
<button data-equals class="span-two">=</button>
</div>
</body>
</html>
3个回答
您没有
this.currentOperandTextElement
,因为它是在类之外定义的
updateDisplay() {
currentOperandTextElement.innerHTML = this.currentOperand
}
我也改为委托
document.querySelector('.calculator-grid').addEventListener('click', (e) => {
const tgt = e.target;
if (tgt.classList.contains('number')) {
calculator.appendNumber(tgt.textContent)
calculator.updateDisplay()
}
})
所有 textContents 都是字符串,因此不需要 number.toString
最后,我不建议使用数据属性作为占位符
这更有意义
<button id="all-clear" class="span-two">AC</button>
<button id="delete">DEL</button>
<button class="operation">÷</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operation">*</button>
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operation">+</button>
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operation">-</button>
<button class="number">.</button>
<button class="number">0</button>
<button id="equals" class="operation span-two">=</button>
class Calculator {
constructor(previousOperandTextElement, currentOperandTextElement) {
this.previousOperandTextElement = previousOperandTextElement
this.currentOperandTextElement = currentOperandTextElement
this.currentOperand = ""
this.clear()
}
clear() {
this.previousOperandTextElement = ''
this.currentOperandTextElement = ''
this.operation = undefined
}
delete() {
}
appendNumber(number) {
this.currentOperand += number
}
chooseOperator(operation) {
}
compute() {
}
updateDisplay() {
currentOperandTextElement.innerHTML = this.currentOperand
}
}
const equalsButton = document.getElementById('equals')
const deleteButton = document.getElementById('delete')
const allClearButton = document.getElementById('all-clear')
const previousOperandTextElement = document.querySelector('[data-previous-operand]')
const currentOperandTextElement = document.querySelector('[data-current-operand]')
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement)
document.querySelector('.calculator-grid').addEventListener('click', (e) => {
const tgt = e.target;
if (tgt.classList.contains('number')) {
calculator.appendNumber(tgt.textContent)
calculator.updateDisplay()
}
})
*,
*::before,
*::after {
box-sizing: border-box;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
font-weight: normal;
}
body {
padding: 0;
margin: 0;
background: linear-gradient(to right, #00AAFF, #00FF6C);
}
.calculator-grid {
display: grid;
justify-content: center;
align-content: center;
min-height: 100vh;
grid-template-columns: repeat(4, 100px);
grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}
.calculator-grid button {
cursor: pointer;
font-size: 2rem;
border: 1px solid white;
outline: none;
background-color: rgba(255, 255, 255, .75);
}
.calculator-grid button:hover {
background-color: rgba(255, 255, 255, .9);
}
.span-two {
grid-column: span 2;
}
.output {
grid-column: 1 / -1;
background-color: rgba(0, 0, 0, 0.75);
border: solid 5px green;
display: flex;
align-items: flex-end;
flex-direction: column;
justify-content: space-between;
padding: 15px;
}
.output .previous-operand {
color: rgba(255, 255, 255, .75);
font-size: 1.5rem;
}
.output .current-operand {
color: rgba(255, 255, 255, .75);
font-size: 2.5rem;
}
<!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>Calculator</title>
<link rel="stylesheet" href="calculator.css">
<script src="calculator.js" defer></script>
</head>
<body>
<div class="calculator-grid">
<div class="output">
<div data-previous-operand class="previous-operand"></div>
<div data-current-operand class="current-operand"></div>
</div>
<button id="all-clear" class="span-two">AC</button>
<button id="delete">DEL</button>
<button class="operation">÷</button>
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operation">*</button>
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operation">+</button>
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operation">-</button>
<button class="number">.</button>
<button class="number">0</button>
<button id="equals" class="operation span-two">=</button>
</div>
</body>
</html>
mplungjan
2021-09-04
您在
Calculator.appendNumber
方法中使用的
currentOperand
变量未定义。
如果第一个参数为
undefined
或
null
,则应使用
Null Coalescing Operator (??)
来提供值。
传递的参数
number
将始终是字符串,因此无需再次对其调用
toString
方法。
appendNumber(number) {
this.currentOpend = (this.currentOperand ?? '') + number;
}
或者在构造函数中设置
this.currentOperand
的值,那么您无需使用
??
运算符
constructor(previousOperandTextElement, currentOperandTextElement) {
...
this.currentOperand = '';
}
并且您的
Calculator.clear
方法应为
clear() {
this.previousOperandTextElement.innerText = '';
this.currentOperandTextElement.innerText = '';
this.operation = undefined;
}
a.mola
2021-09-04
将此代码
appendNumber(number) {
this.currentOperand = this.currentOperand.toString() + number.toString()
>
更改为
appendNumber(number){
this.currentOperand = (this.currentOperand ? this.currentOperand.toString() : ' ') + number.toString();
>
对我有用。尝试此代码一次。
manojlb
2023-07-03