Creating a calculator in JavaScript without using eval() is a common requirement for secure and efficient web applications. This guide will walk you through the process step by step, covering basic implementation, advanced features, and security considerations.
Creating a Basic Calculator
The foundation of any calculator is the ability to perform basic arithmetic operations. Here's how to implement this without using eval().
HTML Structure
Start with a simple HTML structure that includes input fields and buttons for numbers and operations.
Use JavaScript to handle button clicks and perform calculations without eval().
// Basic calculator implementation
document.addEventListener('DOMContentLoaded', function() {
const display = document.getElementById('display');
const buttons = document.querySelectorAll('.buttons button');
let currentInput = '';
let previousInput = '';
let operation = null;
let resetScreen = false;
buttons.forEach(button => {
button.addEventListener('click', () => {
if (button.classList.contains('number')) {
if (currentInput === '0' || resetScreen) {
currentInput = button.textContent;
resetScreen = false;
} else {
currentInput += button.textContent;
}
display.value = currentInput;
}
if (button.classList.contains('operator')) {
if (operation !== null) calculate();
previousInput = currentInput;
operation = button.textContent;
resetScreen = true;
}
if (button.classList.contains('equals')) {
calculate();
operation = null;
}
if (button.classList.contains('clear')) {
currentInput = '0';
previousInput = '';
operation = null;
display.value = currentInput;
}
});
});
function calculate() {
let result;
const prev = parseFloat(previousInput);
const current = parseFloat(currentInput);
if (isNaN(prev) || isNaN(current)) return;
switch (operation) {
case '+':
result = prev + current;
break;
case '-':
result = prev - current;
break;
case '*':
result = prev * current;
break;
case '/':
result = prev / current;
break;
default:
return;
}
currentInput = result.toString();
display.value = currentInput;
operation = null;
}
});
This basic implementation handles numbers, basic operations, and clearing the display. The key is using parseFloat() to convert strings to numbers for calculations rather than using eval().
Adding Advanced Features
Once you have the basic calculator working, you can add more advanced features while maintaining security.
Decimal Point Support
Add support for decimal numbers by checking for existing decimal points.
// Add to the number button click handler
if (button.classList.contains('number')) {
if (button.textContent === '.' && currentInput.includes('.')) return;
// rest of the number handling code
}
Memory Functions
Implement memory functions (M+, M-, MR, MC) to store and recall values.
// Add to your JavaScript
let memory = 0;
buttons.forEach(button => {
// existing code
if (button.classList.contains('memory')) {
switch (button.textContent) {
case 'M+':
memory += parseFloat(currentInput) || 0;
break;
case 'M-':
memory -= parseFloat(currentInput) || 0;
break;
case 'MR':
currentInput = memory.toString();
display.value = currentInput;
break;
case 'MC':
memory = 0;
break;
}
}
});
Keyboard Support
Add keyboard support for better accessibility.
// Add event listener for keyboard
document.addEventListener('keydown', (e) => {
if (e.key >= '0' && e.key <= '9') {
// Simulate number button click
const numberButton = document.querySelector(`.number:nth-child(${parseInt(e.key) + 1})`);
if (numberButton) numberButton.click();
}
if (['+', '-', '*', '/'].includes(e.key)) {
// Simulate operator button click
const operatorButton = Array.from(document.querySelectorAll('.operator'))
.find(btn => btn.textContent === e.key);
if (operatorButton) operatorButton.click();
}
if (e.key === 'Enter' || e.key === '=') {
document.querySelector('.equals').click();
}
if (e.key === 'Escape' || e.key === 'c') {
document.querySelector('.clear').click();
}
if (e.key === '.') {
document.querySelector('.number:nth-child(14)').click();
}
});
Security Considerations
While eval() is dangerous, there are still security considerations when implementing a calculator without it.
Input Validation
Always validate and sanitize user input to prevent injection attacks.
Never trust user input. Always validate numbers, operations, and other inputs before processing them.
Error Handling
Implement proper error handling for edge cases like division by zero.
// Add to the calculate function
function calculate() {
// existing code
if (operation === '/' && current === 0) {
display.value = 'Error';
currentInput = '0';
return;
}
// rest of the calculation code
}
Performance
For complex calculations, consider using web workers to prevent UI freezing.
Worked Examples
Let's walk through some example calculations to see how the calculator works.
Basic Addition
1. Enter 5, then +, then 3. The display shows 5+3.
2. Press =. The calculator shows 8.
Complex Calculation
1. Enter 10, then *, then 5, then +, then 2. The display shows 10*5+2.
2. Press =. The calculator shows 52.
Memory Function Example
1. Enter 100, then M+. The value 100 is stored in memory.
2. Clear the display, enter 50, then M-. The value 50 is subtracted from memory.
3. Press MR. The display shows 50.
FAQ
Why shouldn't I use eval() for calculations?
Using eval() can execute arbitrary code, creating security vulnerabilities. It's safer to use specific parsing and calculation functions.
How do I handle very large numbers?
JavaScript can handle numbers up to 15-17 significant digits. For larger numbers, consider using a library like Big.js or implementing your own arbitrary-precision arithmetic.
Can I add scientific notation support?
Yes, you can add support for scientific notation by checking for 'e' in the input and parsing accordingly.