Máy Tính JavaScript Nâng Cao

Hướng Dẫn Chi Tiết: Làm Máy Tính Bằng JavaScript Từ A Đến Z

Trong thời đại số hóa, việc tạo ra một máy tính trực tuyến bằng JavaScript không chỉ là một dự án thú vị mà còn là một kỹ năng quan trọng đối với các nhà phát triển web. Bài viết này sẽ hướng dẫn bạn từng bước để xây dựng một máy tính hoàn chỉnh với JavaScript, từ những phép tính cơ bản đến các chức năng nâng cao.

1. Các Thành Phần Cơ Bản Của Máy Tính JavaScript

Một máy tính JavaScript典型包括以下核心组件:

  • Giao diện người dùng (UI): Phần hiển thị mà người dùng tương tác, bao gồm các nút bấm và màn hình hiển thị.
  • Logic xử lý: Phần mã JavaScript thực hiện các phép tính dựa trên đầu vào của người dùng.
  • Xử lý sự kiện: Các hàm lắng nghe và phản hồi với hành động của người dùng (như nhấn nút).
  • Hiển thị kết quả: Cập nhật giao diện với kết quả tính toán.

Để bắt đầu, bạn cần chuẩn bị một tệp HTML cơ bản với cấu trúc sau:

<!DOCTYPE html>
<html lang=”vi”>
<head>
  <meta charset=”UTF-8″>
  <meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
  <title>Máy Tính JavaScript</title>
  <link rel=”stylesheet” href=”styles.css”>
</head>
<body>
  <div class=”calculator”>
    <div class=”display”><input type=”text” class=”calculator-screen” value=”” disabled></div>
    <div class=”calculator-keys”>
      <!– Các nút sẽ được thêm ở đây –>
    </div>
  </div>
  <script src=”script.js”></script>
</body>
</html>

2. Xây Dựng Giao Diện Máy Tính

Giao diện máy tính nên bao gồm:

  1. Màn hình hiển thị: Một ô input để hiển thị các phép tính và kết quả.
  2. Các nút chức năng:
    • Các nút số (0-9)
    • Các nút phép toán (+, -, *, /)
    • Nút bằng (=) để thực hiện tính toán
    • Nút xóa (C) để reset máy tính
    • Nút dấu chấm (.) cho số thập phân

Ví dụ về cấu trúc HTML cho các nút:

<div class=”calculator-keys”>
  <button type=”button” class=”operator” value=”+”>+</button>
  <button type=”button” class=”operator” value=”-“>-</button>
  <button type=”button” class=”operator” value=”*”>×</button>
  <button type=”button” class=”operator” value=”/”>÷</button>

  <button type=”button” value=”7″>7</button>
  <button type=”button” value=”8″>8</button>
  <button type=”button” value=”9″>9</button>

  <button type=”button” value=”4″>4</button>
  <button type=”button” value=”5″>5</button>
  <button type=”button” value=”6″>6</button>

  <button type=”button” value=”1″>1</button>
  <button type=”button” value=”2″>2</button>
  <button type=”button” value=”3″>3</button>

  <button type=”button” value=”0″>0</button>
  <button type=”button” class=”decimal” value=”.”>.</button>
  <button type=”button” class=”all-clear” value=”all-clear”>C</button>

  <button type=”button” class=”equal-sign” value=”=”>=</button>
</div>

CSS để стилизация máy tính:

.calculator {
  width: 320px;
  margin: 50px auto;
  border: 1px solid #ccc;
  border-radius: 5px;
  overflow: hidden;
}

.calculator-screen {
  width: 100%;
  font-size: 3rem;
  height: 60px;
  border: none;
  background-color: #252525;
  color: #fff;
  text-align: right;
  padding: 0 10px;
}

.calculator-keys {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 10px;
  padding: 20px;
}

.calculator-keys button {
  height: 60px;
  font-size: 1.5rem;
  border: none;
  border-radius: 3px;
  cursor: pointer;
}

.calculator-keys button:hover {
  background-color: #ddd;
}

3. Logic Xử Lý Phép Tính

Phần quan trọng nhất của máy tính là logic xử lý. Chúng ta cần:

  1. Lắng nghe sự kiện khi người dùng nhấn nút
  2. Xử lý đầu vào (số, phép toán, dấu chấm)
  3. Thực hiện phép tính khi nhấn nút “=”
  4. Hiển thị kết quả hoặc lỗi

Dưới đây là mã JavaScript cơ bản để xử lý máy tính:

const calculator = {
  displayValue: ‘0’,
  firstOperand: null,
  waitingForSecondOperand: false,
  operator: null,
};

function updateDisplay() {
  const display = document.querySelector(‘.calculator-screen’);
  display.value = calculator.displayValue;
}

function inputDigit(digit) {
  const { displayValue, waitingForSecondOperand } = calculator;

  if (waitingForSecondOperand === true) {
    calculator.displayValue = digit;
    calculator.waitingForSecondOperand = false;
  } else {
    calculator.displayValue = displayValue === ‘0’ ? digit : displayValue + digit;
  }
}

function inputDecimal(dot) {
  if (calculator.waitingForSecondOperand === true) {
    calculator.displayValue = ‘0.’;
    calculator.waitingForSecondOperand = false;
    return;
  }

  if (!calculator.displayValue.includes(dot)) {
    calculator.displayValue += dot;
  }
}

function handleOperator(nextOperator) {
  const { firstOperand, displayValue, operator } = calculator;
  const inputValue = parseFloat(displayValue);

  if (operator && calculator.waitingForSecondOperand) {
    calculator.operator = nextOperator;
    return;
  }

  if (firstOperand === null) {
    calculator.firstOperand = inputValue;
  } else if (operator) {
    const result = performCalculation[operator](firstOperand, inputValue);

    calculator.displayValue = String(result);
    calculator.firstOperand = result;
  }

  calculator.waitingForSecondOperand = true;
  calculator.operator = nextOperator;
}

const performCalculation = {
  ‘+’: (firstOperand, secondOperand) => firstOperand + secondOperand,
  ‘-‘: (firstOperand, secondOperand) => firstOperand – secondOperand,
  ‘*’: (firstOperand, secondOperand) => firstOperand * secondOperand,
  ‘/’: (firstOperand, secondOperand) => firstOperand / secondOperand,
  ‘=’: (firstOperand, secondOperand) => secondOperand
};

function resetCalculator() {
  calculator.displayValue = ‘0’;
  calculator.firstOperand = null;
  calculator.waitingForSecondOperand = false;
  calculator.operator = null;
}

const keys = document.querySelector(‘.calculator-keys’);
keys.addEventListener(‘click’, (event) => {
  const { target } = event;

  if (!target.matches(‘button’)) {
    return;
  }

  if (target.classList.contains(‘operator’)) {
    handleOperator(target.value);
    updateDisplay();
    return;
  }

  if (target.classList.contains(‘decimal’)) {
    inputDecimal(target.value);
    updateDisplay();
    return;
  }

  if (target.classList.contains(‘all-clear’)) {
    resetCalculator();
    updateDisplay();
    return;
  }

  if (target.classList.contains(‘equal-sign’)) {
    handleOperator(‘=’);
    updateDisplay();
    return;
  }

  inputDigit(target.value);
  updateDisplay();
});

4. Nâng Cao Máy Tính Với Các Chức Năng Phức Tạp

Để làm cho máy tính của bạn trở nên chuyên nghiệp hơn, bạn có thể thêm các chức năng nâng cao sau:

Chức năng Mô tả Cú pháp JavaScript
Lũy thừa Tính x mũ y (x^y) Math.pow(x, y) hoặc x ** y
Căn bậc hai Tính căn bậc hai của x Math.sqrt(x)
Căn bậc n Tính căn bậc n của x Math.pow(x, 1/n)
Logarit Tính log cơ số 10 của x Math.log10(x)
Logarit tự nhiên Tính ln(x) – log cơ số e Math.log(x)
Sin/Cos/Tan Tính các hàm lượng giác Math.sin(x), Math.cos(x), Math.tan(x)
Phần trăm Tính phần trăm của một số x * y / 100
Giai thừa Tính n! (n giai thừa) Hàm đệ quy hoặc vòng lặp

Ví dụ về cách thêm chức năng lũy thừa:

// Thêm nút lũy thừa vào HTML
<button type=”button” class=”operator” value=”power”>x^y</button>

// Cập nhật hàm handleOperator
function handleOperator(nextOperator) {
  // … mã hiện tại …

  if (nextOperator === ‘power’) {
    calculator.operator = ‘power’;
    calculator.waitingForSecondOperand = true;
    return;
  }
  // … phần còn lại …
}

// Cập nhật đối tượng performCalculation
const performCalculation = {
  // … các phép toán khác …
  ‘power’: (firstOperand, secondOperand) => Math.pow(firstOperand, secondOperand),
  // …
};

5. Xử Lý Lỗi Và Các Trường Hợp Đặc Biệt

Một máy tính tốt cần xử lý được các trường hợp đặc biệt và lỗi:

  • Chia cho 0 (Infinity)
  • Căn bậc hai của số âm (NaN)
  • Logarit của số không dương (NaN)
  • Quá tải số (Overflow)
  • Đầu vào không hợp lệ

Ví dụ về xử lý lỗi:

function performCalculation(operator, firstOperand, secondOperand) {
  try {
    switch(operator) {
      case ‘+’:
        return firstOperand + secondOperand;
      case ‘-‘:
        return firstOperand – secondOperand;
      case ‘*’:
        return firstOperand * secondOperand;
      case ‘/’:
        if (secondOperand === 0) throw new Error(“Không thể chia cho 0”);
        return firstOperand / secondOperand;
      case ‘power’:
        return Math.pow(firstOperand, secondOperand);
      case ‘sqrt’:
        if (firstOperand < 0) throw new Error(“Không thể tính căn của số âm”);
        return Math.sqrt(firstOperand);
      default:
        throw new Error(“Phép toán không hợp lệ”);
    }
  } catch (error) {
    alert(error.message);
    return NaN;
  }
}

6. Tối Ưu Hóa Và Các Tips Nâng Cao

Để cải thiện hiệu suất và trải nghiệm người dùng:

  1. Sử dụng Service Worker: Cho phép máy tính hoạt động offline.
  2. Thêm hiệu ứng âm thanh: Phản hồi âm thanh khi nhấn nút.
  3. Hỗ trợ bàn phím: Cho phép người dùng sử dụng bàn phím vật lý.
  4. Lưu lịch sử tính toán: Sử dụng localStorage để lưu các phép tính trước đó.
  5. Responsive Design: Tối ưu hóa cho mọi kích thước màn hình.
  6. Thêm chủ đề (themes): Cho phép người dùng chuyển đổi giữa các chủ đề màu sắc.
  7. Hỗ trợ đa ngôn ngữ: Cho phép chuyển đổi ngôn ngữ giao diện.

Ví dụ về hỗ trợ bàn phím:

document.addEventListener(‘keydown’, (event) => {
  const { key } = event;

  if (/[0-9]/.test(key)) {
    inputDigit(key);
    updateDisplay();
  } else if (key === ‘.’) {
    inputDecimal(key);
    updateDisplay();
  } else if ([‘+’, ‘-‘, ‘*’, ‘/’].includes(key)) {
    handleOperator(key);
    updateDisplay();
  } else if (key === ‘Enter’ || key === ‘=’) {
    handleOperator(‘=’);
    updateDisplay();
  } else if (key === ‘Escape’) {
    resetCalculator();
    updateDisplay();
  }
});

7. Triển Khai Và Chia Sẻ Máy Tính Của Bạn

Sau khi hoàn thành máy tính, bạn có thể:

  • Triển khai lên GitHub Pages: Miễn phí và dễ dàng.
  • Sử dụng Netlify/Vercel: Triển khai nhanh chóng với CI/CD.
  • Nhúng vào website: Sử dụng iframe hoặc tích hợp trực tiếp.
  • Đóng gói thành PWA: Cho phép cài đặt như một ứng dụng.
  • Chia sẻ trên npm: Nếu bạn tạo thành một thư viện.

Các bước triển khai lên GitHub Pages:

  1. Tạo một repository mới trên GitHub
  2. Đẩy mã nguồn của bạn lên repository
  3. Vào Settings > Pages
  4. Chọn nhánh chính (main/master)
  5. Chọn thư mục gốc (root) hoặc /docs nếu bạn sử dụng thư mục docs
  6. Nhấn Save – máy tính của bạn sẽ có sẵn tại username.github.io/repo-name

8. Các Nguồn Tài Nguyên Hữu Ích

Để tìm hiểu sâu hơn về việc tạo máy tính bằng JavaScript, bạn có thể tham khảo các nguồn sau:

9. So Sánh Các Thư Viện Máy Tính JavaScript Phổ Biến

Nếu bạn không muốn xây dựng từ đầu, có thể sử dụng các thư viện có sẵn:

Thư Viện Đặc Điểm Kích Thước Stars trên GitHub Link
Math.js Thư viện toán học toàn diện với máy tính tích hợp ~1MB 13.8k mathjs.org
Calculator.js Thư viện máy tính đơn giản, nhẹ ~10KB 1.2k GitHub
Big.js Thư viện tính toán số thập phân chính xác cao ~15KB 4.5k big.js
Decimal.js Thư viện số thập phân chính xác cho JavaScript ~50KB 4.3k decimal.js
Algebrite Thư viện toán học biểu tượng (đại số) ~500KB 1.8k algebrite.org

10. Các Dự Án Máy Tính JavaScript Để Tham Khảo

Một số dự án máy tính JavaScript mở nguồn đáng chú ý:

Kết Luận

Việc tạo một máy tính bằng JavaScript không chỉ giúp bạn củng cố kiến thức về ngôn ngữ này mà còn mang lại một sản phẩm thực tế có thể sử dụng. Từ những phép tính cơ bản đến các chức năng nâng cao, máy tính JavaScript có thể được mở rộng vô hạn tùy theo nhu cầu của bạn.

Bắt đầu với một máy tính đơn giản, sau đó dần dần thêm các chức năng phức tạp hơn khi bạn cảm thấy tự tin. Đừng quên tối ưu hóa mã nguồn, xử lý lỗi cẩn thận và tạo trải nghiệm người dùng mượt mà.

Với những kiến thức trong bài viết này, bạn hoàn toàn có thể tạo ra một máy tính JavaScript chuyên nghiệp, đáp ứng được hầu hết các nhu cầu tính toán thông thường và cả một số nhu cầu nâng cao. Hãy bắt tay vào thực hành và sáng tạo với dự án của riêng bạn!

Leave a Reply

Your email address will not be published. Required fields are marked *