2009-09-01 33 views
13

Trong javascript, là có bất kỳ khác nhau giữa hai:MyFunction() vs window.setTimeout ('MyFunction()', 0)?

// call MyFunction normal way 

MyFunction(); 

// call MyFunction with setTimeout to 0 // 

window.setTimeout('MyFunction()', 0); 

Lý do tôi hỏi là vì thời gian gần đây tình cờ gặp những tình huống mà các mã chỉ hoạt động nếu tôi sử dụng setTimeout(0) để gọi hàm. Để hiểu biết của tôi, setTimeout(0) giống hệt như gọi một hàm trực tiếp bởi vì bạn không đặt bất kỳ sự chậm trễ nào. Nhưng từ những gì tôi thấy nó hoạt động như thế nào trong mã, setTimeout(0) dường như được thực thi cuối cùng.

Ai đó có thể làm rõ chính xác cách setTimeout(0) thực sự được gọi theo thứ tự của phần còn lại của cuộc gọi chức năng khác không?

+1

http: // stackoverflow.com/questions/779379/why-does-settimeoutfn-0-sometimes-help –

Trả lời

17

setTimeout() luôn làm cho khối JavaScript được xếp hàng đợi để thực thi. Đó là vấn đề khi nào nó sẽ được thực hiện, được quyết định bởi sự chậm trễ được cung cấp. Gọi setTimeout() với độ trễ là 0, sẽ dẫn đến trình thông dịch JavaScript nhận ra rằng nó đang bận (thực hiện chức năng hiện tại), và trình thông dịch sẽ lập lịch khối tập lệnh được thực hiện khi ngăn xếp cuộc gọi hiện tại trống (trừ khi có các khối tập lệnh khác cũng được xếp hàng đợi).

Có thể mất một thời gian dài để ngăn xếp cuộc gọi trống, đó là lý do tại sao bạn thấy sự chậm trễ trong thực thi. Điều này chủ yếu là do tính chất đơn luồng của JavaScript trong một ngữ cảnh cửa sổ duy nhất.

Để hoàn thành, MyFunction() sẽ ngay lập tức thực hiện chức năng. Sẽ không có hàng đợi liên quan.

PS: John Resig has some useful notes on how the JavaScript timing mechanism works.

PPS: Lý do mã của bạn "có vẻ hoạt động" chỉ khi bạn sử dụng setTimeout (fn(), 0), là do trình duyệt có thể cập nhật DOM chỉ khi ngăn xếp cuộc gọi hiện tại hoàn tất. Do đó, khối JavaScript tiếp theo sẽ nhận ra các thay đổi DOM, điều này hoàn toàn có thể xảy ra trong trường hợp của bạn. Gọi lại setTimeout() luôn tạo một ngăn xếp cuộc gọi mới.

3

Tôi đoán rằng thời gian chờ chỉ bắt đầu khi trang được tải đầy đủ, trong khi chỉ đơn giản 'MyFunction()' sẽ thực thi ngay sau khi được xử lý.

+1

Đó là chính xác. Không cần đoán. –

+1

@Marius thiết lập một trang thử nghiệm và thử nó - các hàm nội tuyến sẽ kích hoạt tất cả các cách xuống trang trước khi một setTimeout (0) được khai báo ở các vụ cháy hàng đầu. –

+0

Đã thử nó, bạn đã đúng, và loại bỏ bình luận của tôi, nhưng không phải trước khi bạn nhìn thấy nó. – Marius

0

Bộ hẹn giờ sẽ cố gắng thực hiện khi chuỗi hiện tại của bạn được thực hiện. Điều này phụ thuộc vào nơi bạn gọi window.setTimeout(). Nếu nó nằm trong một thẻ javascript, nhưng không phải bên trong một hàm, thì nó sẽ được gọi khi kết thúc của thẻ javascript đạt được. Ví dụ:

<html> 
<script type="text/javascript"> 
setTimeout(function(){alert("hello")},0); 
var d=Number(new Date())+1000; 
while(Number(new Date())<d){ 

} 
alert("hi"); 
</script> 
</html> 

Nếu bạn gọi setTimeout bên trong một hàm là kết quả của một occuring sự kiện, ví dụ onload, sau đó nó sẽ đợi cho đến khi trở về chức năng xử lý sự kiện:

<html> 
<script type="text/javascript"> 
document.addEventListener("mousedown",function(){ 
    setTimeout(function(){alert("hello")},0); 
    var d=Number(new Date())+1000; 
    while(Number(new Date())<d){ 

    } 
    alert("hi"); 
}, true); 
</script> 
</html> 

Nó là không thể để làm cho một luồng trong JavaScript chờ trong khi một luồng khác đang chạy. Trình lắng nghe sự kiện sẽ đợi cho đến khi luồng hiện tại được thực hiện trước khi chúng bắt đầu chạy.

Ngoại lệ duy nhất là Web Worker, nhưng chúng chạy trong một tệp khác và cách duy nhất để liên lạc giữa chúng là sử dụng trình lắng nghe sự kiện, vì vậy trong khi bạn có thể gửi thư trong khi người khác đang làm việc, nó sẽ không nhận được tin nhắn đó cho đến khi nó được thực hiện, hoặc nó tự kiểm tra tin nhắn.

+0

Mọi thứ bạn nói đều đúng theo nghĩa chung (JavaScript là đơn luồng) nhưng setTimeout (0) sẽ kích hoạt khi trang được tải, không phải khi nó chạm vào cuối khối tập lệnh. –

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