1. 程式人生 > >從無到有實現一個網頁計算器

從無到有實現一個網頁計算器

// 計算器建構函式,主入口
var Calculator = function Calculator () {
	// 左側數值
	this.left = null;
	// 右側數值
	this.right = null;
	// 運算子
	this.operator = null;
	// 當前輸入模式,"left"表示當前輸入的是左側數值,"right"表示當前輸入的右側數值
	this.mode = "left";
	// 匹配等號
	this.equals = [ "=" ];
	// 特殊運算子
	this.specialOperators = [ "AC" ];
	// 匹配基本運算子
	this.basicOperators = [ "÷", "×", "-", "+" ];
	// 基本運算子對映
	this.basicOperatorMappings = {
		"÷": "/",
		"×": "*",
		"-": "-",
		"+": "+"
	};
};

// 初始化
Calculator.prototype.init = function () {
	this.monitorInstance = new Monitor();
	this.numberInstance = new Number();
	this.operatorInstance = new Operator();
	
	this.monitorInstance.init();
	this.numberInstance.init();
	this.operatorInstance.init();
	
	this.subscribe();
};

// 取消訂閱事件
Calculator.prototype.unsubscribe = function () {
	EventEmitter.remove("calculator.number");
	EventEmitter.remove("calculator.operator");
};

// 訂閱事件
Calculator.prototype.subscribe = function () {
	EventEmitter.subscribe("calculator.number", (number) => { this.onNumberInput(number); });
	EventEmitter.subscribe("calculator.operator", (operator) => { this.onOperatorInput(operator); });
};

// 監聽數值輸入
Calculator.prototype.onNumberInput = function (number) {
	// 當前輸入的為左側數值
	if (this.mode === "left") this.left = number;
	// 當前輸入的為右側數值
	if (this.mode === "right") this.right = number;
};

// 監聽運算子輸入
Calculator.prototype.onOperatorInput = function (operator) {
	// 當前輸入的是等號,[ "=" ]
	if (this.equals.includes(operator)) {
		// 排除不合法操作
		if (this.operator == null) return;
		if (this.left == null && this.right == null) return;
		if (this.left == null || this.right == null) return;
		this.calcResult();
	// 當前輸入的基本運算子,[ "÷", "×", "-", "+" ]
	} else if (this.basicOperators.includes(operator)) {
		// 排除不合法操作
		if (this.left == null) return;
		
		// 獲取真實操作運算子,防止[ "÷", "×" ]這類非法運算子參與計算
		this.operator = this.basicOperatorMappings[operator];
		// 切換當前輸入為右側數字
		this.mode = "right";
		
		// 重置當前Number的value,以便重新輸入右側數值
		EventEmitter.emit("calculator.number.reset");
	// 特殊運算子[ "AC" ]
	} else if (this.specialOperators.includes(operator)) {
		this.reset();
	}
};

// 計算結果
Calculator.prototype.calcResult = function () {
	// 根據左側、右側數值加上運算子計算出結果
	// 將結果作為左側數值繼續參與計算
	var result = this.left = eval(`${this.left}${this.operator}${this.right}`);
	
	// 切換當前輸入為右側數字
	this.mode = "right";
	// 重置當前Number的value,以便重新輸入右側數值
	EventEmitter.emit("calculator.number.reset");
	
	// 顯示計算結果
	EventEmitter.emit("calculator.show", result);
};

// 重置
Calculator.prototype.reset = function () {
	this.monitorInstance.destroy();
	this.numberInstance.destroy();
	this.operatorInstance.destroy();
	this.unsubscribe();
	
	this.left = null;
	this.right = null;
	this.operator = null;
	this.mode = "left";
	
	this.init();
	EventEmitter.emit("calculator.number.reset");
};