| A:Onetime | B:Manytimes | C:C / CE | D:% / ± | |
|---|---|---|---|---|
| 0 | Push Num | Push Num | Push Num | Push Num |
| 1 | Push Operation | Push Operation | Push C / CE | Push '%' / '±' |
| 2 | Push Num | Push Num | Clear | Push Operation |
| 3 | Push = |
Show Result | END |
Push Num -> A2 |
| 4 | Show Result | Push Operation | Push = -> A4 |
|
| 5 | END |
Push = -> A4 |
押した時の挙動
| Push | Numbers | Operations |
|---|---|---|
| 0 | Display | none |
| 1 | 2nd digit | END |
| 2 | 3rd digit | |
| 3 | ......... |
± と ÷ の挙動
| ± | % | |
|---|---|---|
| 0 | Push Number | Push Number |
| 1 | Push ± | Push % |
| 2 | Multiply -1 by Num | Multiply 0.01 by Num |
| 3 |
0.01を掛ける-1を掛けるp要素でリスト化する(=を押したタイミング)=のとき)または途中の結果を表示するnull & undefined
null: 空であることを明示するundefined: 定義されていない、または参照することを想定していない==,===&&,||,!do...while,while: 条件式の真偽に応じてループを制御するfor: 指定された回数だけループするfor...in: 連想配列の中身を順に処理するfor...of: 配列の要素を順に処理するforEach: 配列の内容を順に取り出しながら、決められた処理を実行するisNaNオペランドとは オペランドとは、コンピュータの演算における値や変数のことである。
オぺランドは演算の種類や内容を表す演算子(オペレータ)によって演算対象となるもので、
例えば「7×3」という計算式があれば、「7」と「3」がオペランドとなる。
「7×3」の演算における「×」はオペレータとして、計算の内容を規定する。
if (numberText === '00' && result.value === '0') {
// '00'を押したときは何もしない
// すでに '0' が表示されている場合は何もしない
return;
} else if (result.value === '0' &&
(numberText !== '00' || numberText !== '0')) {
// 表示が'0'かつ入力が'00'か'0'ではないとき、
// 最初の '0' を数字に置き換え
result.value = numberText;
} else if (result.value === '0' && numberText === '.') {
// 0が表示されており、かつ'.'を入力したとき
// '0'を'0.'に置き換える
result.value = '0.';
}
// else if (result.value === '0' && numberText !== '.') {//!
// // '0'が表示されており、かつ数字以外の入力がある場合は
// // 最初の '0' を数字に置き換え
// result.value = numberText;
// }
else if (result.value.indexOf('.') !== -1 && numberText === '.') {
// 小数点が含まれている場合でも、
// さらに小数点を入力しようとしたときは何もしない.
// 小数点が表示されており、かつ小数点を入力したとき
// 何もしない
return;
} else {
// 数字を連続して入力する
result.value += numberText;
}

if (numberText === '00' && result.value === '0') {
// すでに '0' が表示されている場合は'00'を入力しても何もしない
//// console.log(result.value, numberText);
return;
} else if (result.value === '0' &&
(numberText !== '00' || numberText !== '0')) {
// 表示が'0'かつ入力が'00'か'0'ではないとき、最初の'0'を数字に置き換え
//// console.log(result.value, numberText);
result.value = numberText; // result.value を更新
} else if (result.value === '0' && numberText === '.') {
// 0が表示されており、かつ'.'を入力したとき末尾に'.'を追加する
//// console.log(result.value, numberText);
result.value = '0.';
} else if (result.value.indexOf('.') !== -1 && numberText === '.') {
// 既に小数点が含まれている場合、'.'を追加しない
//// console.log(result.value, numberText);
return;
} else {
// 数字を連続して入力する
//// console.log(result.value, numberText);
result.value += numberText; // result.value を更新
}
result.value = '0';
numbers.forEach(number => {
number.addEventListener('click', () => {
const numberText = number.getAttribute('data-numbers');
if (numberText === '00' && result.value === '0') {
console.log(result.value, numberText);
return;
} else if (result.value === '0' &&
(numberText !== '00' || numberText !== '0')) {
console.log(result.value, numberText);
result.value = numberText;
} else if (result.value === '0' && numberText === '.') {
console.log(result.value, numberText);
result.value = '0' + '.';
} else if (result.value.indexOf('.') !== -1 && numberText === '.') {
console.log(result.value, numberText);
return;
} else {
console.log(result.value, numberText);
result.value += numberText;
}
});
});
ifを入れ子にすることで、数値を画面に表示するresult.valueに
0.を表示することができた。
それまでは、'.'ボタンを押しても期待する表示'0.'ではなく'.'のみが
表示されてしまっていた。
問題があったのは
} else if (result.value === '0' &&
(numberText !== '00' || numberText !== '0')) {
console.log(result.value, numberText);
result.value = numberText;
この部分で、'.'を押した際にこの条件分岐に引っかかり、
result.value = '.'が実行されていた。
そのためにその下の分岐のresult.value = '0' + '.';
が実行されることなく、結果として'0.'が表示されなかった。
if (result.value === '0' && numberText === '00') {
console.log(result.value, numberText, 'A');
result.value = '0';
} else if (
(result.value === '0' && numberText !== '00') ||
(result.value === '0' && numberText !== '0')
) {
if (numberText === '.') {
result.value = '0.';
console.log(result.value, numberText, 'Ba');
} else {
result.value = numberText;
console.log(result.value, numberText, 'Bb');
}
} else if (result.value.indexOf('.') !== -1 && numberText === '.') {
console.log(result.value, numberText, 'C');
return;
} else {
console.log(result.value, numberText, 'D');
result.value += numberText;
}
配列にいれてしまえ -> evelを使わざるをえない
配列はやめる
入れた後はオペランドをどこかに保存してresult.valueをクリアする
operations.forEach(operator => {以下に、
//? 1. 数字(オペランド(A))を押した
//? 2. オペレーターを押した
//? 1. オペランド(A)を変数`firstOperand`に格納する
//? 3. 数字を押すと、その数字をオペランド(B)の入力を受け付ける
//? 1. オペランド(B)を変数`secondOperand`に格納する
//? 4. オペレータかイコールか
//? 1. `nextStage`変数で、次のアクションを示す
//? 2. オペレータが押された時`nextState = 'number';`
//? 数字が押されたとき`nextState = 'operator';`
//? 3. `number`ならオペレータを入力させる.
//? `operator`なら数字を入力させる
//! 分岐点(operator or equal)
//? 5. オペレータを押すことで...
//? 1. `nextStage`を`number`に変更
//? ?. 一時的な結果を`temporaryResult`として表示
//? 3. オペランド(B)を変数`secondOperand`に格納
//? 4. `firstOperand`をメソッドの第一引数にする <- ??
//? ?. 一時的な結果を`firstOperand`に代入
//! 分岐点(number or operand)
//? 6. イコールを押すことで...
//? 1. `nextStage`を変更
//? 2. メソッドの計算結果を表示する

.png)
const calculator = new Calculator(20, 10);
console.log(`addition: ${calculator.add()}`);
console.log(`subtraction: ${calculator.subtract()}`);
console.log(`multiplication: ${calculator.multiply()}`);
console.log(`division: ${calculator.divide()}`);
console.log(`percent: ${calculator.percent()}`);
console.log(`plusMinus: ${calculator.plusOrMinus()}`);
console.log('--------------------');
thisthisキーワードは、
new演算子によって生成されるインスタンス(つまり自分自身)を表すものです。
evalについてevalは文字列を引数として扱う。
evalは算術式として扱う。evalは他の方法よりも低速である。警告: 文字列から JavaScript を実行することは、
非常に大きなセキュリティリスクを伴います。
eval()を使用すると、悪意のある者が任意のコードを実行することが
あまりにも簡単になります。
下記のeval()を使わないでください!を参照してください。
// ボタンがクリックされたときの処理を設定
buttons.forEach(button => {
const buttonText = button.innerText; // ボタンのテキストを取得
button.addEventListener('click', () => {
// ここで buttonText を使用して処理を行う
// result.value += buttonText; //`result`に数字を表示する
// もしオペレータを押したら、`result.value`を変数に格納しディスプレイをクリアし、
// 各種メソッドを呼び出す
// ----------
if (buttonText !== isNaN) { //buttonがNumberであるとき
console.log(buttonText);
} else if(buttonText === isNaN){ //buttonがNumberでないとき
result.value += buttonText;
}
});
});
result.value = '0'; //* 初期の表示は`0`
numbers.forEach(number => {
number.addEventListener('click', () => {
const numberText = number.getAttribute('data-numbers'); // 押された数字
// console.log(`Number:${numberText}`);
if (result.value === '0' && numberText === '00') {
// すでに '0' が表示されている場合は
// '00'を入力しても'0'を表示する
// console.log(result.value, numberText, 'A');
result.value = '0';
} else if (
(result.value === '0' && numberText !== '00') ||
(result.value === '0' && numberText !== '0')
) {
// 表示が'0'かつ入力が'00'または
// 表示が'0'かつ入力が'0'のとき
// 表示の'0'を'.'か'0~9'までの数字に置換
if (numberText === '.') {
result.value = '0.';
// console.log(result.value, numberText, 'Ba');
} else {
result.value = numberText;
// console.log(result.value, numberText, 'Bb');
}
// result.value を更新
} else if (result.value.indexOf('.') !== -1 && numberText === '.') { // 既に小数点が含まれている場合、'.'を追加しない
// console.log(result.value, numberText, 'C');
return;
} else { // 数字を連続して入力する
// console.log(result.value, numberText, 'D');
result.value += numberText; // result.value を更新
}
// console.log('--------------------');
});
});
class Calculator {
constructor(pre, next, result) {
//
this.pre = pre;
this.next = next;
this.result = result;
}
add() {
this.result = this.pre + this.next;
return this.result;
}
subtract() {
this.result = this.pre - this.next;
return this.result;
}
multiply() {
this.result = this.pre * this.next;
return this.result;
}
divide() {
if (this.next === 0) {
throw new Error("0で除算はできません");
}
this.result = this.pre / this.next;
return this.result;
}
percent() {
this.result = this.pre * 0.01;
return this.result;
}
plusOrMinus() {
this.result = -this.pre;
return this.result;
}
getResult() {
return this.result;
}
}
const buttons = document.querySelectorAll('button');
const numbers = document.querySelectorAll('button[data-numbers');
const clear = document.querySelector('button[data-clear]');
const clearEntries = document.querySelector('button[data-clearEntries]');
const operations = document.querySelectorAll('button[data-operation]');
const equal = document.querySelector('button[data-equal]');
const result = document.getElementById('result');
let nextStage = 'operator';
let firstOperand = null;
let secondOperand = null;
let temporaryResult = null;
let selectedOperand = null;
const calculator = new Calculator(firstOperand, secondOperand);
result.value = '0';
numbers.forEach(number => {
number.addEventListener('click', () => {
const numberText = number.getAttribute('data-numbers');
if (firstOperand !== null && nextStage === 'number') {
result.value = '';
} else if (secondOperand !== null) {
result.value = '';
}
if (result.value === '0' && numberText === '00') {
result.value = '0';
} else if (
(result.value === '0' && numberText !== '00') ||
(result.value === '0' && numberText !== '0')
) {
if (numberText === '.') {
result.value = '0.';
} else {
result.value = numberText;
}
} else if (
(result.value.indexOf('.') !== -1) &&
(numberText === '.')
) {
return;
} else {
result.value += numberText;
}
nextStage = 'operator';
console.log(`nextStage:${nextStage}`);
});
});
operations.forEach(operator => {
operator.addEventListener('click', () => {
const opeText = operator.innerHTML;
if (firstOperand === null) {
firstOperand = result.value;
} else if (secondOperand === null) {
secondOperand = result.value;
}
switch (opeText) {
case '+':
console.log(`Pushed '+'`);
selectedOperand = '+';
break;
case '-':
console.log(`Pushed '-'`);
break;
case '÷':
console.log(`Pushed '÷'`);
break;
case '×':
console.log(`Pushed '×'`);
break;
case '%':
console.log(`Pushed '%'`);
break;
case '±':
console.log(`Pushed '±'`);
break;
default:
console.log(`他のオペレータが押された...?`);
}
nextStage = 'number';
console.log(`nextStage:${nextStage}, selectedOperand:${selectedOperand}`);
});
});
clear.addEventListener('click', () => {
console.log(`(${clear.innerHTML}):Clear`);
});
clearEntries.addEventListener('click', () => {
console.log(`(${clearEntries.innerHTML}):ClearEntries`);
});
equal.addEventListener('click', () => {
console.log(`(${equal.innerHTML}):Equal`);
switch (selectedOperand) {
case '+':
const adds = calculator.add();
console.log(adds);
}
if (secondOperand === null) {
secondOperand = result.value;
}
console.log(`FirstOperand:${firstOperand}, SecondOperand:${secondOperand}`);
});
if (result.value === '0' && numberText === '00') {
// 0の時,00を押しても...0のまま.
// result.value = '0';
return;
} else if (
(result.value === '0' && numberText !== '00') ||
(result.value === '0' && numberText !== '0')) {
// 0の時,0か00以外を押した時に...
if (numberText === '.') {// '.'を押すと...
result.value = '0.';// '0.'を表示.
} else { // '.'を押さないときは...
result.value = numberText;// 数字を表示.
}
} else if (
(result.value.indexOf('.') !== -1) && // 表示に'.'があり...
(numberText === '.')) { //かつ'.'が入力されたら...
return; //何もしない.
} else { // 以上の条件に当てはまらないとき...
result.value += numberText; //数字を後ろに追加する
}
if ((result.value === '0' && numberText !== '00') ||
(result.value === '0' && numberText !== '0')) {
if (numberText === '.') {
result.value = '0.';
} else {
result.value = numberText;
}
} else if (result.value === '0' && numberText === '00') {
return;
} else if (
(result.value.indexOf('.') !== -1) &&
(numberText === '.')) {
return;
} else {
result.value += numberText;
}