eval
là xấu xa trong JavaScript! Trang Eval Eval tuyên bố:
Tính năng lỗi thời này là lỗi thời. Mặc dù nó vẫn được hỗ trợ bởi các trình duyệt, việc sử dụng của nó không được khuyến khích trong các dự án mới. Cố gắng tránh sử dụng nó.
This feature is obsolete. Although it is still supported by browsers, its usage is discouraged in new projects. Try to avoid using it.
eval
thực thi mã chứa chuỗi, ví dụ:
eval["var x = 'Hello from eval!';"];
console.log[x];
eval
nêu ra một số vấn đề:
- Bảo mật: Chuỗi của bạn có thể được tiêm các lệnh khác bằng các tập lệnh của bên thứ ba hoặc đầu vào người dùng.
- Gỡ lỗi: Thật khó để gỡ lỗi lỗi - bạn không có số dòng hoặc điểm rõ ràng của thất bại.
- Tối ưu hóa: Trình thông dịch JavaScript không nhất thiết phải tổng hợp mã vì nó có thể thay đổi. Mặc dù các phiên dịch viên đã trở nên ngày càng hiệu quả, nhưng nó gần như chắc chắn chạy chậm hơn mã gốc.
Thật không may, eval
rất mạnh mẽ và nó dễ dàng cho các nhà phát triển ít kinh nghiệm hơn để lạm dụng lệnh.
Mặc dù các cảnh báo, eval
vẫn hoạt động - ngay cả ở chế độ nghiêm ngặt - nhưng bạn thường có thể tránh nó. Trước đây, nó chủ yếu được sử dụng để khử các chuỗi JSON-serialize nhưng giờ chúng ta có phương pháp
// function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
0 an toàn hơn.Tuy nhiên, điều gì sẽ xảy ra nếu chúng ta có tên hàm trong một chuỗi, ví dụ:
// function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
Làm thế nào để chúng ta thực thi chức năng
// function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
1 mà không cần sử dụng eval
? Gần đây tôi đã gặp phải tình huống này khi sử dụng API lịch sử HTML5; Phương pháp Pushstate won cho phép bạn lưu trữ một tham chiếu trực tiếp đến một hàm để bạn cần xác định tên của nó là một chuỗi. Bạn cũng có thể phải đối mặt với những thách thức tương tự khi sử dụng nhân viên web hoặc bất kỳ API nào khác nơi các đối tượng được tuần tự hóa.Giải pháp thực thi đơn giản và an toàn nhất mà không có giải pháp Eval là một loạt các điều kiện, ví dụ:
// function we want to run
var fnstring = "runMe";
switch [fnstring] {
case "functionX": functionX[]; break;
case "functionY": functionY[]; break;
case "functionZ": functionZ[]; break;
case "runMe": runMe[]; break;
}
Nó rất an toàn, nhưng khá kém hiệu quả và đau đớn khi viết nếu bạn có hàng tá các cuộc gọi chức năng có thể.
Một giải pháp tốt hơn là sử dụng đối tượng
// function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
3 tham chiếu cửa sổ hiện tại và tất cả các mục trong đó. Chúng ta có thể kiểm tra xem // function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
4 có sẵn dưới dạng đối tượng trong // function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
3 hay không và chạy nó nếu nó là một hàm, ví dụ:// function we want to run
var fnstring = "runMe";
// find object
var fn = window[fnstring];
// is object a function?
if [typeof fn === "function"] fn[];
Bạn có thể thực hiện các kiểm tra khác nếu cần thiết để đảm bảo chức năng có tên dự kiến.
Điều gì sẽ xảy ra nếu chức năng chúng ta muốn gọi có tham số - có lẽ được lưu trữ trong một mảng? Không vấn đề gì; Chúng tôi chỉ cần sử dụng phương pháp
// function we want to run
var fnstring = "runMe";
function runMe[] {
// do stuff
}
6:// function name and parameters to pass
var fnstring = "runMe";
var fnparams = [1, 2, 3];
// find object
var fn = window[fnstring];
// is object a function?
if [typeof fn === "function"] fn.apply[null, fnparams];
Vì vậy, một lý do khác để ngừng sử dụng eval
. Như một phần thưởng, giải pháp này an toàn hơn, ít có lỗi hơn, dễ gỡ lỗi hơn và thường sẽ thực hiện nhanh hơn. Tôi hy vọng nó sẽ giúp.