eval() ใช้รันโค้ดจากสตริง แต่มีปัญหาสำคัญ 3 ข้อ: ช้า, ไม่ปลอดภัย, ยากต่อการ Debug
ตัวอย่างการใช้งาน (เพื่อการศึกษา)
<html>
<body>
<script>
var a = 30;
var b = 12;
var res1 = eval("a * b") + "<br>";
var res2 = eval("5 + 10") + "<br>";
document.write(res1); // 360
document.write(res2); // 15
</script>
</body>
</html>
3 เหตุผลหลักที่ควรหลีกเลี่ยง
1. ช่องโหว่ด้านความปลอดภัย (Security Vulnerability)
// อันตรายมาก! User input ไปยัง eval โดยตรง
var userInput = document.getElementById('input').value;
eval(userInput); // ผู้ใช้พิมพ์: alert('hacked'); หรือ fetch('/api/delete', {method:'DELETE'})
// ตัวอย่างโจมตีจริง
// userInput: "fetch('/api/user/delete', {method:'DELETE', credentials:'include'})"
2. ประสิทธิภาพต่ำ (Performance)
- เบราว์เซอร์ไม่สามารถ compile/optimize โค้ดใน eval ได้ล่วงหน้า
- ต้อง parse และ compile ทุกครั้งที่เรียก
- ช้ากว่าโค้ดทั่วไป 10-100 เท่า
- สร้าง scope ใหม่ทุกครั้ง (memory overhead)
3. Debugging และ Tooling ยาก
- Stack trace ไม่ชี้บรรทัดที่แท้จริง
- Breakpoint ไม่ทำงานใน eval code
- Linter/TypeScript ไม่วิเคราะห์ได้
- Minifier ไบอัปติไมซ์ได้
ทางเลือกที่ปลอดภัยและเร็วกว่า
1. JSON.parse() - สำหรับข้อมูล JSON
// แทน eval('(' + jsonStr + ')')
const data = JSON.parse(jsonStr);
2. Object/Map Lookup - สำหรับ Dynamic Function Call
const actions = {
'save': saveData,
'delete': deleteData,
'update': updateData
};
// แทน eval(action + '()')
if (actions[userAction]) {
actions[userAction]();
}
3. Function Constructor (ยังมีความเสี่ยง แต่ควบคุมได้ดีกว่า)
// เฉพาะเมื่อจำเป็นต้องสร้างฟังก์ชันจากสตริง
const fn = new Function('a', 'b', 'return a + b');
fn(1, 2); // 3
4. สำหรับ Math Expression - ใช้ Parser Library
// ใช้ math.js, expr-eval, หรือเขียน parser เอง // ไม่มีเหตุผลที่จะใช้ eval สำหรับคำนวณคณิตศาสตร์
กรณีที่ eval() ยอมรับได้ (น้อยมาก)
- Code runner/editor (CodePen, JSFiddle) - sandboxed environment
- Template engine แบบ custom (ที่ sanitize input แล้ว)
- Legacy code ที่ refactor ไม่ได้ทันที
สรุป
"eval is evil" - Douglas Crockford
ไม่มีเหตุผลที่จะใช้ eval() ในโค้ดสมัยใหม่ มีทางเลือกที่ดีกว่าทุกด้าน