概述
階乘計算器是一個專業的數學計算工具,專為學生、教師、算法工程師和數學愛好者設計,能夠精確計算0到170範圍內非負整數的階乘值。 本工具採用純前端架構,完全在瀏覽器端運行,零網路傳輸,確保數據的絕對隱私和安全性。 提供迭代算法優化、大數字格式化、輸入驗證、歷史記錄管理、複製功能、雙語界面等專業功能。
🔒 隱私保護承諾
🔒 Privacy Protection Promise
所有數學計算處理都在您的瀏覽器本地進行,數據不會上傳到任何伺服器,確保您的計算數據完全安全。
技術架構與核心設計
整體架構設計
Overall Architecture Design
技術項目 | 實作方式 | 設計考量 |
---|---|---|
前端框架 | 純 JavaScript (ES6+) | 零依賴,最小化載入時間 |
數學算法 | 迭代階乘計算 | 時間複雜度 O(n),避免遞迴栈溢位 |
大數字處理 | JavaScript BigInt + 格式化 | 支援超大階乘值的精確計算 |
數據持久化 | localStorage 歷史記錄 | 本地儲存,隱私安全 |
用戶介面 | 響應式設計 + 雙語系統 | 跨設備兼容性與國際化 |
核心類別架構
Core Class Architecture
class FactorialCalculator {
constructor() {
this.currentLanguage = 'zh';
this.translations = {
zh: { /* 中文翻譯字典 */ },
en: { /* 英文翻譯字典 */ }
};
this.history = this.loadHistory();
this.init();
}
init() {
this.setupElements();
this.setupEventListeners();
this.setupGlobalLanguageListener();
this.updateLanguage();
this.updateHistoryDisplay();
}
// 主要計算流程
calculateFactorial() {
const result = this.factorial(number);
this.displayResult(number, result);
this.addToHistory(number, result);
}
}
關鍵功能實現
1. 迭代階乘算法優化
1. Iterative Factorial Algorithm Optimization
採用迭代算法實現階乘計算,避免遞迴調用可能導致的堆疊溢位問題。 支援0到170範圍內的精確計算,時間複雜度為O(n),空間複雜度為O(1)。
// 高效能迭代階乘算法實作
factorial(n) {
// 基本情況:0! = 1, 1! = 1
if (n === 0 || n === 1) return 1;
// 迭代計算避免遞迴栈溢位
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
2. 大數字格式化與顯示系統
2. Large Number Formatting & Display System
處理階乘計算產生的大數字,使用千分位分隔符提升可讀性。 自動格式化輸出,支援多語言數字格式化標準。
// 數字格式化系統
formatNumber(num) {
// 使用內建 toLocaleString 添加千分位分隔符
return num.toLocaleString();
}
generateCalculationProcess(n) {
if (n === 0 || n === 1) {
return `${n}! = 1`;
}
if (n <= 10) {
// 對於小數字,顯示完整計算過程
const steps = [];
for (let i = n; i >= 1; i--) {
steps.push(i.toString());
}
return `${n}! = ${steps.join(' × ')} = ${this.formatNumber(this.factorial(n))}`;
} else {
// 對於大數字,顯示簡化過程
return `${n}! = ${n} × ${n-1} × ${n-2} × ... × 2 × 1 = ${this.formatNumber(this.factorial(n))}`;
}
}
3. 智能輸入驗證與錯誤處理
3. Intelligent Input Validation & Error Handling
多層次輸入驗證確保只接受有效的非負整數,包括空值檢查、數值格式驗證、範圍限制和整數檢查。 針對不同錯誤類型提供具體的錯誤訊息和指導建議。
// 完整的輸入驗證系統
calculateFactorial() {
const input = this.numberInput.value.trim();
const t = this.translations[this.currentLanguage];
// 清除之前的錯誤
this.clearError();
// 第一層:空值檢查
if (input === '') {
this.showError(t.errorEmpty);
return;
}
const num = parseFloat(input);
// 第二層:檢查是否為整數
if (!Number.isInteger(num)) {
this.showError(t.errorNotInteger);
return;
}
// 第三層:檢查是否為非負數
if (num < 0) {
this.showError(t.errorNegative);
return;
}
// 第四層:檢查是否超出安全範圍
if (num > 170) {
this.showError(t.errorTooLarge);
return;
}
// 驗證通過,執行計算
const result = this.factorial(num);
const formattedResult = this.formatNumber(result);
this.displayResult(num, result, formattedResult);
this.addToHistory(num, formattedResult);
}
實作細節
以下是完整程式碼實作,按功能模組分類展示。點擊卡片標題可展開查看詳細程式碼:
📦 核心階乘計算器類別
核心架構:FactorialCalculator 類別包含完整的階乘計算功能,包括建構函數初始化、翻譯系統、歷史記錄管理和主要計算流程。 採用模組化設計,每個功能職責清晰分離,支援0-170範圍的精確階乘計算。
// 階乘計算器主類別 - 完整實作
class FactorialCalculator {
constructor() {
// 當前語言設定,預設為中文
this.currentLanguage = 'zh';
// 完整的雙語翻譯字典
this.translations = {
zh: {
title: '🔢 階乘計算器',
description: '計算非負整數的階乘值,適用於數學教育和算法分析',
inputLabel: '請輸入整數:',
placeholder: '例如:5',
inputHint: '範圍:0 到 170',
calcButton: '計算階乘',
clearButton: '清除',
resultLabel: '計算結果:',
copyButton: '複製結果',
copySuccess: '已複製',
defaultResult: '請輸入一個數字並點擊計算',
infoTitle: '💡 關於階乘',
infoDescription: '階乘(factorial)是所有小於及等於該數的正整數的乘積。',
infoExamples: '例如:5! = 5 × 4 × 3 × 2 × 1 = 120
特殊情況:0! = 1,1! = 1',
historyTitle: '計算歷史',
clearHistory: '清除歷史',
// 錯誤訊息完整定義
errorEmpty: '請輸入一個數字',
errorNotInteger: '請輸入非負整數',
errorNegative: '請輸入非負整數(大於等於0)',
errorTooLarge: '數字過大,請輸入小於等於170的整數',
errorInvalid: '輸入格式錯誤,請輸入有效的整數'
},
en: {
title: '🔢 Factorial Calculator',
description: 'Calculate factorial values for non-negative integers, suitable for math education and algorithm analysis',
inputLabel: 'Enter Integer:',
placeholder: 'e.g., 5',
inputHint: 'Range: 0 to 170',
calcButton: 'Calculate Factorial',
clearButton: 'Clear',
resultLabel: 'Result:',
copyButton: 'Copy Result',
copySuccess: 'Copied',
defaultResult: 'Enter a number and click calculate',
infoTitle: '💡 About Factorial',
infoDescription: 'Factorial is the product of all positive integers less than or equal to that number.',
infoExamples: 'Example: 5! = 5 × 4 × 3 × 2 × 1 = 120
Special cases: 0! = 1, 1! = 1',
historyTitle: 'Calculation History',
clearHistory: 'Clear History',
// 錯誤訊息英文版本
errorEmpty: 'Please enter a number',
errorNotInteger: 'Please enter a non-negative integer',
errorNegative: 'Please enter a non-negative integer (≥ 0)',
errorTooLarge: 'Number too large, please enter an integer ≤ 170',
errorInvalid: 'Invalid input format, please enter a valid integer'
}
};
// 載入歷史記錄,提供持久化支援
this.history = this.loadHistory();
// 執行初始化
this.init();
}
init() {
// 初始化順序很重要:元素→事件→語言→歷史記錄
this.setupElements();
this.setupEventListeners();
this.setupGlobalLanguageListener();
this.updateLanguage();
this.updateHistoryDisplay();
}
}
🌐 全域語言系統整合
語言同步機制:與全站語言系統完美整合,監聽 languageChanged 事件,即時響應語言切換。 處理初始化時序問題,支援動態更新所有UI元素,包括錯誤訊息和歷史記錄的語言切換。
// 完整的語言系統整合實作
setupGlobalLanguageListener() {
// 監聽全域語言切換事件
window.addEventListener('languageChanged', (event) => {
this.currentLanguage = event.detail.language;
this.updateLanguage();
});
// 處理全局語言系統加載時序問題
const checkGlobalLanguage = () => {
if (window.globalI18n) {
this.currentLanguage = window.globalI18n.currentLanguage;
this.updateLanguage();
return true;
}
return false;
};
// 如果全局語言系統還未載入,等待100ms後重試
if (!checkGlobalLanguage()) {
setTimeout(() => {
checkGlobalLanguage();
}, 100);
}
}
updateLanguage() {
const t = this.translations[this.currentLanguage];
// 更新所有UI文字元素
document.getElementById('main-title').textContent = t.title;
document.getElementById('main-description').textContent = t.description;
document.getElementById('input-label').textContent = t.inputLabel;
document.getElementById('number-input').placeholder = t.placeholder;
document.getElementById('input-hint').textContent = t.inputHint;
document.getElementById('calc-btn-text').textContent = t.calcButton;
document.getElementById('clear-btn-text').textContent = t.clearButton;
document.getElementById('result-label').textContent = t.resultLabel;
document.getElementById('copy-btn-text').textContent = t.copyButton;
document.getElementById('info-title').textContent = t.infoTitle;
document.getElementById('info-description').textContent = t.infoDescription;
document.getElementById('info-examples').innerHTML = t.infoExamples;
document.getElementById('history-title-text').textContent = t.historyTitle;
document.getElementById('clear-history-text').textContent = t.clearHistory;
// 智能更新結果顯示區域
if (this.resultDisplay.textContent.includes('請輸入') ||
this.resultDisplay.textContent.includes('Enter a number')) {
this.resultDisplay.textContent = t.defaultResult;
}
}
// 參數化翻譯函數 - 支援動態參數插入
t(key, params = {}) {
let text = this.translations[this.currentLanguage][key] || key;
// 替換參數:{number} -> 實際數字, {result} -> 計算結果
Object.keys(params).forEach(param => {
text = text.replace(`{${param}}`, params[param]);
});
return text;
}
🎯 DOM 元素初始化與事件系統
元素管理與事件綁定:完整的 DOM 元素查詢、緩存和事件綁定系統。包括輸入框、按鈕、結果顯示、歷史記錄等所有交互元素的管理。 支援鍵盤快捷鍵(Enter 鍵觸發計算)、即時輸入驗證、手機數字鍵盤優化等用戶體驗功能。
// DOM 元素初始化和事件處理完整實作
setupElements() {
// 快取所有重要的 DOM 元素,避免重複查詢
this.numberInput = document.getElementById('number-input');
this.calculateBtn = document.getElementById('calculate-btn');
this.clearBtn = document.getElementById('clear-btn');
this.resultDisplay = document.getElementById('result-display');
this.calculationProcess = document.getElementById('calculation-process');
this.resultActions = document.getElementById('result-actions');
this.copyBtn = document.getElementById('copy-btn');
this.errorMessage = document.getElementById('error-message');
this.historySection = document.getElementById('history-section');
this.historyList = document.getElementById('history-list');
// 驗證重要元素是否存在
if (!this.numberInput || !this.calculateBtn || !this.resultDisplay) {
console.error('Factorial Calculator: Required DOM elements not found');
return;
}
}
setupEventListeners() {
// 計算按鈕 - 主要功能觸發
this.calculateBtn.addEventListener('click', () => {
this.calculateFactorial();
});
// 清除按鈕 - 重置所有狀態
this.clearBtn.addEventListener('click', () => {
this.clearAll();
});
// 複製按鈕 - 複製結果到剪貼簿
this.copyBtn.addEventListener('click', () => {
this.copyResult();
});
// Enter鍵快速計算 - 鍵盤友好操作
this.numberInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.calculateFactorial();
}
});
// 即時輸入驗證 - 提供即時反饋
this.numberInput.addEventListener('input', () => {
this.clearError();
this.validateInput();
});
// 手機數字鍵盤優化
this.numberInput.addEventListener('focus', () => {
this.numberInput.setAttribute('inputmode', 'numeric');
});
}
// 即時輸入驗證系統
validateInput() {
const value = this.numberInput.value.trim();
// 空值不顯示錯誤,允許用戶清空輸入
if (value === '') {
this.numberInput.classList.remove('error');
return true;
}
const num = parseFloat(value);
const isInteger = Number.isInteger(num);
const isInRange = num >= 0 && num <= 170;
// 即時視覺反饋
if (!isInteger || !isInRange) {
this.numberInput.classList.add('error');
return false;
}
this.numberInput.classList.remove('error');
return true;
}
// 清除所有狀態的完整實作
clearAll() {
this.numberInput.value = '';
this.numberInput.classList.remove('error');
this.resultDisplay.textContent = this.translations[this.currentLanguage].defaultResult;
this.resultDisplay.classList.remove('success');
this.calculationProcess.style.display = 'none';
this.resultActions.style.display = 'none';
this.clearError();
this.numberInput.focus(); // 自動聚焦提升用戶體驗
}
// 錯誤狀態管理
showError(message) {
this.errorMessage.textContent = message;
this.errorMessage.classList.add('show');
this.numberInput.classList.add('error');
}
clearError() {
this.errorMessage.classList.remove('show');
this.numberInput.classList.remove('error');
}
⚙️ 階乘算法引擎與計算流程
高效能算法實作:採用迭代算法實現階乘計算,避免遞迴栈溢位問題。包含完整的輸入驗證流程、 錯誤處理機制、邊界條件處理,支援0-170範圍內的精確計算。時間複雜度O(n),空間複雜度O(1)。
// 完整的階乘計算流程與算法實作
calculateFactorial() {
const input = this.numberInput.value.trim();
const t = this.translations[this.currentLanguage];
// 清除之前的錯誤狀態
this.clearError();
// 第一層驗證:空值檢查
if (input === '') {
this.showError(t.errorEmpty);
return;
}
const num = parseFloat(input);
// 第二層驗證:檢查是否為整數
if (!Number.isInteger(num)) {
this.showError(t.errorNotInteger);
return;
}
// 第三層驗證:檢查是否為非負數
if (num < 0) {
this.showError(t.errorNegative);
return;
}
// 第四層驗證:檢查是否超出安全計算範圍
// JavaScript 能精確處理的最大階乘約為170!
if (num > 170) {
this.showError(t.errorTooLarge);
return;
}
// 驗證通過,執行階乘計算
const result = this.factorial(num);
const formattedResult = this.formatNumber(result);
// 顯示結果和計算過程
this.displayResult(num, result, formattedResult);
// 添加到歷史記錄
this.addToHistory(num, formattedResult);
}
// 核心階乘算法 - 迭代實作
factorial(n) {
// 邊界條件:0! = 1, 1! = 1
if (n === 0 || n === 1) return 1;
// 迭代計算,避免遞迴栈溢位
// 對於大數字(如170!),這比遞迴更安全
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
// 可選:為超大數字添加中斷檢查
// 雖然170!在現代瀏覽器中計算很快,但這是個好習慣
if (result === Infinity) {
console.warn(`Factorial calculation reached Infinity at ${i}`);
break;
}
}
return result;
}
// 數字格式化 - 添加千分位分隔符
formatNumber(num) {
// 處理特殊值
if (num === Infinity) return '∞';
if (isNaN(num)) return 'NaN';
// 使用瀏覽器內建的本地化格式化
// 自動根據用戶語言環境添加適當的分隔符
try {
return num.toLocaleString();
} catch (error) {
// 備用格式化方法
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
}
// 生成計算過程顯示
generateCalculationProcess(n) {
if (n === 0 || n === 1) {
return `${n}! = 1`;
}
if (n <= 10) {
// 對於小數字,顯示完整的乘法過程
const steps = [];
for (let i = n; i >= 1; i--) {
steps.push(i.toString());
}
const process = steps.join(' × ');
const result = this.formatNumber(this.factorial(n));
return `${n}! = ${process} = ${result}`;
} else if (n <= 20) {
// 對於中等數字,顯示部分過程
const result = this.formatNumber(this.factorial(n));
return `${n}! = ${n} × ${n-1} × ${n-2} × ... × 3 × 2 × 1 = ${result}`;
} else {
// 對於大數字,顯示簡化過程和科學記數法
const result = this.formatNumber(this.factorial(n));
const scientificNotation = this.factorial(n).toExponential(3);
return `${n}! = ${result} ≈ ${scientificNotation}`;
}
}
🎨 結果顯示與複製功能系統
視覺化結果系統:動態生成結果顯示內容,包括格式化數字、計算過程和操作按鈕。 支援現代 Clipboard API 和 fallback 機制的複製功能,提供視覺反饋和錯誤處理。適配不同瀏覽器的兼容性需求。
// 完整的結果顯示系統
displayResult(input, rawResult, formattedResult) {
// 更新主要結果顯示
this.resultDisplay.textContent = `${input}! = ${formattedResult}`;
this.resultDisplay.classList.add('success');
// 生成並顯示計算過程
const process = this.generateCalculationProcess(input);
this.calculationProcess.textContent = process;
this.calculationProcess.style.display = 'block';
// 顯示操作按鈕(複製等)
this.resultActions.style.display = 'flex';
// 可選:為超大結果添加額外資訊
if (input > 100) {
const digitCount = rawResult.toString().length;
const additionalInfo = document.createElement('div');
additionalInfo.className = 'result-info';
additionalInfo.textContent = `結果包含 ${digitCount} 位數字`;
// 檢查是否已存在資訊,避免重複添加
const existingInfo = this.resultDisplay.parentNode.querySelector('.result-info');
if (existingInfo) {
existingInfo.remove();
}
this.resultDisplay.parentNode.appendChild(additionalInfo);
}
}
// 現代剪貼簿API複製功能
async copyResult() {
const text = this.resultDisplay.textContent;
const t = this.translations[this.currentLanguage];
try {
// 優先使用現代 Clipboard API
await navigator.clipboard.writeText(text);
// 成功複製的視覺反饋
this.showCopySuccess(t.copySuccess);
} catch (err) {
console.warn('Clipboard API 不可用,使用 fallback 方法:', err);
// 使用傳統的 fallback 方法
this.fallbackCopyTextToClipboard(text);
}
}
// 複製成功的視覺反饋
showCopySuccess(message) {
const originalText = this.copyBtn.innerHTML;
// 更新按鈕狀態
this.copyBtn.innerHTML = `✅ ${message}`;
this.copyBtn.classList.add('copied');
// 2秒後恢復原始狀態
setTimeout(() => {
this.copyBtn.innerHTML = originalText;
this.copyBtn.classList.remove('copied');
}, 2000);
}
// Fallback 複製方法(兼容舊瀏覽器)
fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
const t = this.translations[this.currentLanguage];
// 設置文本區域屬性
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
// 選中並複製
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
if (successful) {
this.showCopySuccess(t.copySuccess);
} else {
console.error('Fallback 複製失敗');
this.showCopyError('複製失敗,請手動選擇文字');
}
} catch (err) {
console.error('Fallback 複製方法執行失敗:', err);
this.showCopyError('複製功能不可用');
} finally {
// 清理臨時元素
document.body.removeChild(textArea);
}
}
// 複製錯誤處理
showCopyError(message) {
const originalText = this.copyBtn.innerHTML;
// 顯示錯誤狀態
this.copyBtn.innerHTML = `❌ ${message}`;
this.copyBtn.classList.add('copy-error');
// 3秒後恢復
setTimeout(() => {
this.copyBtn.innerHTML = originalText;
this.copyBtn.classList.remove('copy-error');
}, 3000);
}
// 檢查剪貼簿API支援狀態
isClipboardSupported() {
return navigator.clipboard &&
typeof navigator.clipboard.writeText === 'function' &&
window.isSecureContext; // HTTPS 環境才支援
}
// 智能複製方法選擇
async smartCopy() {
if (this.isClipboardSupported()) {
await this.copyResult();
} else {
this.fallbackCopyTextToClipboard(this.resultDisplay.textContent);
}
}
🛠️ 用戶體驗優化與響應式設計
歷史記錄管理:提供完整的計算歷史記錄功能,包括本地儲存、重複項目過濾、數量限制、快速重算等功能。 採用響應式設計支援各種設備,具備完整的CSS樣式系統,包括深色模式支援、動畫效果、手機端優化等。
// 歷史記錄完整管理系統
addToHistory(input, result) {
const entry = {
input: input,
result: result,
timestamp: new Date().getTime()
};
// 移除重複項目,避免歷史記錄中出現相同計算
this.history = this.history.filter(item => item.input !== input);
// 添加到開頭,最新的計算顯示在最上方
this.history.unshift(entry);
// 限制歷史記錄數量為10個,避免佔用過多儲存空間
if (this.history.length > 10) {
this.history = this.history.slice(0, 10);
}
// 即時保存和更新顯示
this.saveHistory();
this.updateHistoryDisplay();
}
updateHistoryDisplay() {
// 如果沒有歷史記錄,隱藏整個歷史區塊
if (this.history.length === 0) {
this.historySection.classList.remove('show');
return;
}
// 顯示歷史記錄區塊
this.historySection.classList.add('show');
// 動態生成歷史記錄項目
const historyHTML = this.history.map(entry => {
const timeAgo = this.getTimeAgo(entry.timestamp);
return `
${entry.input}! = ${entry.result}
${timeAgo}
`;
}).join('');
this.historyList.innerHTML = historyHTML;
}
// 從歷史記錄快速重新計算
loadFromHistory(input) {
this.numberInput.value = input;
this.calculateFactorial();
// 提供視覺反饋
this.numberInput.focus();
this.numberInput.select();
}
// 清除歷史記錄功能
clearHistory() {
this.history = [];
this.saveHistory();
this.updateHistoryDisplay();
// 提供操作確認反饋
const clearBtn = document.getElementById('clear-history');
const originalText = clearBtn.textContent;
clearBtn.textContent = '已清除';
clearBtn.style.background = '#48bb78';
setTimeout(() => {
clearBtn.textContent = originalText;
clearBtn.style.background = '';
}, 1500);
}
// 本地儲存操作
loadHistory() {
try {
const saved = localStorage.getItem('factorial-calculator-history');
const parsed = saved ? JSON.parse(saved) : [];
// 驗證載入的數據格式
if (Array.isArray(parsed)) {
return parsed.filter(item =>
item.input !== undefined &&
item.result !== undefined &&
item.timestamp !== undefined
);
}
return [];
} catch (err) {
console.error('載入歷史記錄失敗:', err);
return [];
}
}
saveHistory() {
try {
localStorage.setItem('factorial-calculator-history', JSON.stringify(this.history));
} catch (err) {
console.error('儲存歷史記錄失敗:', err);
// 嘗試清理舊數據後重新儲存
if (err.name === 'QuotaExceededError') {
this.history = this.history.slice(0, 5); // 減少到5個記錄
try {
localStorage.setItem('factorial-calculator-history', JSON.stringify(this.history));
} catch (secondErr) {
console.error('再次儲存失敗,清除歷史記錄');
this.history = [];
}
}
}
}
// 時間格式化輔助函數
getTimeAgo(timestamp) {
const now = new Date().getTime();
const diff = now - timestamp;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days} 天前`;
if (hours > 0) return `${hours} 小時前`;
if (minutes > 0) return `${minutes} 分鐘前`;
return '剛剛';
}
// 響應式佈局檢測與調整
handleResponsiveLayout() {
const isMobile = window.innerWidth <= 768;
const container = document.querySelector('.factorial-calculator-standalone');
if (isMobile) {
container.classList.add('mobile-layout');
// 手機端優化:簡化顯示,增大觸控區域
this.optimizeForMobile();
} else {
container.classList.remove('mobile-layout');
this.optimizeForDesktop();
}
}
// 手機端優化
optimizeForMobile() {
// 確保數字鍵盤在手機上正確顯示
this.numberInput.setAttribute('inputmode', 'numeric');
this.numberInput.setAttribute('pattern', '[0-9]*');
// 增大按鈕觸控區域
const buttons = document.querySelectorAll('.calc-button');
buttons.forEach(btn => {
btn.style.minHeight = '48px';
btn.style.fontSize = '1.2rem';
});
}
// 桌面端優化
optimizeForDesktop() {
// 桌面端可以顯示更多詳細資訊
const buttons = document.querySelectorAll('.calc-button');
buttons.forEach(btn => {
btn.style.minHeight = '';
btn.style.fontSize = '';
});
}
🚀 工具初始化與生命週期管理
完整生命週期管理:從實例化到初始化的完整流程,包括DOM就緒檢測、錯誤處理、性能監控、清理機制等。 提供可靠的初始化序列,確保所有組件正確載入,支援熱重載和錯誤恢復機制。
// 階乘計算器全局實例和初始化管理
class FactorialCalculatorManager {
constructor() {
this.instance = null;
this.isInitialized = false;
this.initStartTime = performance.now();
// 確保DOM完全載入後初始化
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => this.init());
} else {
// DOM已經載入完成
this.init();
}
}
init() {
try {
console.log('Factorial Calculator: 開始初始化...');
// 檢查必要的DOM元素
if (!this.checkRequiredElements()) {
console.error('Factorial Calculator: 缺少必要的DOM元素');
return;
}
// 創建主要實例
this.instance = new FactorialCalculator();
this.isInitialized = true;
// 性能監控
const initTime = performance.now() - this.initStartTime;
console.log(`Factorial Calculator: 初始化完成,耗時 ${initTime.toFixed(2)}ms`);
// 設置全局引用,方便調試和外部訪問
window.factorialCalc = this.instance;
// 設置錯誤處理
this.setupErrorHandling();
// 設置性能監控
this.setupPerformanceMonitoring();
} catch (error) {
console.error('Factorial Calculator: 初始化失敗', error);
this.handleInitializationError(error);
}
}
checkRequiredElements() {
const requiredIds = [
'number-input', 'calculate-btn', 'clear-btn',
'result-display', 'error-message'
];
for (const id of requiredIds) {
if (!document.getElementById(id)) {
console.error(`Missing required element: ${id}`);
return false;
}
}
return true;
}
setupErrorHandling() {
// 全局錯誤處理
window.addEventListener('error', (event) => {
if (event.filename && event.filename.includes('factorial')) {
console.error('Factorial Calculator 運行時錯誤:', event.error);
this.handleRuntimeError(event.error);
}
});
// Promise 錯誤處理
window.addEventListener('unhandledrejection', (event) => {
console.error('Factorial Calculator Promise 錯誤:', event.reason);
});
}
setupPerformanceMonitoring() {
// 監控計算性能
const originalCalculate = this.instance.calculateFactorial.bind(this.instance);
this.instance.calculateFactorial = () => {
const start = performance.now();
const result = originalCalculate();
const end = performance.now();
const calcTime = end - start;
if (calcTime > 100) {
console.warn(`Factorial calculation took ${calcTime.toFixed(2)}ms`);
}
return result;
};
}
handleInitializationError(error) {
// 顯示用戶友好的錯誤訊息
const errorDiv = document.createElement('div');
errorDiv.className = 'init-error';
errorDiv.innerHTML = `
🚫 階乘計算器初始化失敗
抱歉,工具無法正常載入。請嘗試重新整理頁面。
`;
const container = document.querySelector('.factorial-calculator-standalone');
if (container) {
container.appendChild(errorDiv);
}
}
handleRuntimeError(error) {
if (this.instance && this.instance.showError) {
this.instance.showError('計算過程中出現錯誤,請重試');
}
}
// 清理資源(頁面卸載時)
cleanup() {
if (this.instance) {
// 儲存最後狀態
if (this.instance.saveHistory) {
this.instance.saveHistory();
}
// 清理事件監聽器
window.removeEventListener('languageChanged', this.instance.updateLanguage);
// 清理全局引用
if (window.factorialCalc === this.instance) {
delete window.factorialCalc;
}
this.instance = null;
this.isInitialized = false;
}
}
// 熱重載支援(開發環境)
reload() {
console.log('Factorial Calculator: 執行熱重載...');
this.cleanup();
setTimeout(() => {
this.init();
}, 100);
}
}
// 頁面卸載時清理資源
window.addEventListener('beforeunload', () => {
if (window.factorialCalcManager) {
window.factorialCalcManager.cleanup();
}
});
// 鍵盤快捷鍵支援
document.addEventListener('keydown', (event) => {
// 確保計算器已初始化且輸入框沒有焦點時才響應快捷鍵
if (!window.factorialCalc || event.target.tagName === 'INPUT') return;
switch(event.key) {
case 'c':
case 'C':
// C鍵清除
if (event.ctrlKey || event.metaKey) return; // 避免干擾複製操作
window.factorialCalc.clearAll();
event.preventDefault();
break;
case 'Enter':
// Enter鍵計算(當沒有輸入框焦點時)
window.factorialCalc.calculateFactorial();
event.preventDefault();
break;
case 'Escape':
// Esc鍵清除錯誤狀態
window.factorialCalc.clearError();
event.preventDefault();
break;
}
});
// 響應式佈局監聽
window.addEventListener('resize', () => {
if (window.factorialCalc && window.factorialCalc.handleResponsiveLayout) {
// 防抖處理,避免頻繁觸發
clearTimeout(window.factorialCalc.resizeTimeout);
window.factorialCalc.resizeTimeout = setTimeout(() => {
window.factorialCalc.handleResponsiveLayout();
}, 250);
}
});
// 創建全局管理器實例
const factorialCalcManager = new FactorialCalculatorManager();
// 暴露到全局作用域供調試使用
window.factorialCalcManager = factorialCalcManager;
// 開發環境輔助功能
if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
// 開發模式專用功能
window.debugFactorialCalc = {
reload: () => factorialCalcManager.reload(),
getHistory: () => factorialCalcManager.instance ? factorialCalcManager.instance.history : [],
clearHistory: () => factorialCalcManager.instance ? factorialCalcManager.instance.clearHistory() : null,
testLarge: (n) => {
if (factorialCalcManager.instance) {
factorialCalcManager.instance.numberInput.value = n;
factorialCalcManager.instance.calculateFactorial();
}
}
};
console.log('Factorial Calculator Debug Tools Available:', window.debugFactorialCalc);
}
效能優化策略
計算效能優化
Calculation Performance Optimization
- 迭代算法:採用 O(n) 時間複雜度的迭代算法,避免遞迴栈溢位
- 範圍限制:限制輸入範圍在 0-170,確保 JavaScript 數值精度
- 即時驗證:在用戶輸入時進行即時驗證,減少無效計算
- 結果緩存:歷史記錄避免重複計算相同數值
用戶介面效能
User Interface Performance
- DOM 緩存:初始化時緩存所有 DOM 元素,避免重複查詢
- 事件委託:使用事件委託減少記憶體佔用
- 防抖機制:輸入驗證和語言切換使用防抖,避免頻繁執行
- 漸進載入:歷史記錄按需顯示,避免初始渲染負擔
安全性與隱私考量
- 完全本地運行:所有計算在瀏覽器端執行,數據不傳輸到伺服器
- 輸入淨化:嚴格的輸入驗證防止惡意輸入
- XSS 防護:所有動態內容使用 textContent 而非 innerHTML
- 本地儲存安全:歷史記錄僅儲存在用戶本地,可隨時清除
瀏覽器兼容性
瀏覽器 | 最低版本 | 支援功能 |
---|---|---|
Chrome | 60+ | 完整功能,包括現代 Clipboard API |
Firefox | 55+ | 完整功能支援 |
Safari | 12+ | 完整功能,iOS 12+ 支援 |
Edge | 79+ | 完整功能支援 |
未來改進方向
- 大數運算:整合 BigInt 支援更大範圍的階乘計算
- 科學記數法:提供科學記數法顯示選項
- 計算歷史匯出:支援歷史記錄 CSV 匯出功能
- 進階數學功能:添加 Gamma 函數、Stirling 近似等相關功能
- 視覺化:添加階乘增長趨勢圖表
總結
階乘計算器展現了現代 Web 應用在數學工具領域的最佳實踐,通過純前端技術實現了高效、安全、用戶友好的計算體驗。 其模組化的程式碼架構、完整的雙語支援、響應式設計和本地隱私保護等特性,為類似數學教育工具的開發提供了優秀的參考範例。