2012-07-27 23 views
5

Tôi biết rằng evalsetTimeout cả hai có thể chấp nhận một chuỗi là tham số (1) và tôi biết rằng tôi không nên sử dụng điều này. Tôi chỉ tò mò tại sao lại có một sự khác biệt:Sự khác biệt giữa eval và mã chuỗi thực thi setTimeout

!function() { 
    var foo = 123; 
    eval("alert(foo)"); 
}(); 

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

là người đầu tiên sẽ làm việc, và lần thứ hai sẽ đưa ra một lỗi: foo is not defined

như thế nào họ thực hiện đằng sau những cảnh?

+1

foo không nằm ngoài phạm vi trước khi gọi lại setTimeout được gọi? –

+1

Tại sao lại rối tung với những thứ xấu xa ^^ Đừng sử dụng một trong hai thứ này :) – Andreas

+0

Một điểm quan sát có liên quan thú vị [ở đây] (https://stackoverflow.com/q/3492015/465053). – RBT

Trả lời

4

Xem reference of setTimeout on MDN.

String literals are evaluated in the global context, so local symbols in the context where setTimeout() was called will not be available when the string is evaluated as code.

Ngược lại, chuỗi ký tự được chuyển đến eval() được thực thi trong ngữ cảnh cuộc gọi đến eval.

+0

và mã được chuyển đến 'eval' sẽ thực thi trong ngữ cảnh' eval' đang thực hiện? – wong2

+0

Chính xác, chuỗi ký tự được đánh giá "tại chỗ" và có quyền truy cập vào các biến được xác định trong ngữ cảnh đó. – Wolfram

+0

@ wong2 thực sự nó phụ thuộc vào cách bạn gọi là 'eval'. Trong các trình duyệt hiện đại, eval sau đây nằm trong phạm vi toàn cầu: http://jsfiddle.net/4p9QY/ bởi vì nó là eval gián tiếp. Dưới đây là ví dụ về các cuộc gọi eval gián tiếp http://perfectionkills.com/global-eval-what-are-the-options/#indirect_eval_call_examples – Esailija

2

setTimeout's eval được thực thi bổ sung trong phạm vi toàn cầu, do đó, nó không biết về foo.

Dưới đây là reference để sao lưu nó lên:

String literals are evaluated in the global context, so local symbols in the context where setTimeout() was called will not be available when the string is evaluated as code.

0
!function() { 
    var foo = 123; 
    eval("alert(foo)"); 
}(); 

Khi thực thi mã này, javascript sẽ giả vờ dòng 3 cho biết "alert (foo)". Foo được định nghĩa trong phạm vi chức năng.

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

Khi thực thi mã này, javascript sẽ nhập một hàm mới; cụ thể là function() {alert(foo)}. Trong phạm vi chức năng 'mới' đó, foo không được xác định.

1

setTimeout có nhiều tham số hơn tham chiếu hàm và thời gian chờ. Bất kỳ điều gì đã nhập quá thời gian chờ sẽ được chuyển đến hàm của bạn dưới dạng tham số.

setTimeout(myFunction(param1, param2), 0, param1, param2); 
0

Là một bổ sung cho câu trả lời đúng, đây là một lời kêu gọi eval rằng sẽ cung cấp cho bạn những hành vi tương tự, và lỗi trong trường hợp này:

!function() { 
    var foo = 123; 
    window.eval("alert(foo)"); // <- note the window.eval, this is important and changes the behavior of the `eval` function 
}(); 

!function() { 
    var foo = 123; 
    setTimeout("alert(foo)", 0); 
}(); 

bài viết trên blog này đi sâu vào các loại khác nhau của eval: http://perfectionkills.com/global-eval-what-are-the-options/

Các vấn đề liên quan