1. 程式人生 > >異步、作用域、閉包

異步、作用域、閉包

執行函數 完成後 ise har 但是 循環 text rip doc

for(var i=0;i<=3;i++){ setTimeout(function() { console.log(i) }, 10);}

答案:打印4次4

這道題涉及了異步、作用域、閉包

settimeout是異步執行,10ms後往任務隊列裏面添加一個任務,只有主線上的全部執行完,才會執行任務隊列裏的任務,當主線執行完成後,i是4,所以此時再去執行任務隊列裏的任務時,i全部是4了。對於打印4次是:

每一次for循環的時候,settimeout都執行一次,但是裏面的函數沒有被執行,而是被放到了任務隊列裏面,等待執行,for循環了4次,就放了4次,當主線程執行完成後,才進入任務隊列裏面執行。   (註意:for循環從開始到結束的過程,需要維持幾微秒或幾毫秒。) 當我把var 變成let 時 for(let i=0;i<=3;i++){ setTimeout(function() { console.log(i) }, 10);} 打印出的是:0,1,2,3 當解決變量作用域,

因為for循環頭部的let不僅將i綁定到for循環快中,事實上它將其重新綁定到循環體的每一次叠代中,確保上一次叠代結束的值重新被賦值。setTimeout裏面的function()屬於一個新的域,通過 var 定義的變量是無法傳入到這個函數執行域中的,通過使用 let 來聲明塊變量,這時候變量就能作用於這個塊,所以 function就能使用 i 這個變量了;這個匿名函數的參數作用域 和 for參數的作用域 不一樣,是利用了這一點來完成的。這個匿名函數的作用域有點類似類的屬性,是可以被內層方法使用的。

查了一下百度的一個答案:

setTimeout是一次執行函數,這裏是10ms後執行,僅僅執行一次;for(var i=0;i<=3;i++),i的每次取值都是執行setTimeout這個函數,並沒有執行setTimeout裏面的function(即閉包函數),setTimeout裏面的function是有setTimeout的定時觸動的,也就是10ms後執行,也就是說i從0~3時,一共執行了4次的setTimeout()函數,此時的i的值是4,由於for語句的執行速度遠小於1秒,所以,1秒後,由setTimeout()函數定時觸動的閉包函數function()開始執行,alert(i);i的值已經是4了,所以相繼打印4次i.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">
            function btn1 () { // 通過var定義的變量,作用域是整個封閉函數,是全域的 。通過let定義的變量,作用域是在塊級或是子塊中。
//                for (let i = 0; i < 5; i++) { // 0 1 2 3 4
// setTimeout(function() { // console.log(i) // }, 1000*i); // } for (let i = 0; i < 5; i++) { setTimeout(function() { // 5 5 5 5 5 console.log(i) }, 1000*i); } } function btn2 () { for (var i = 0; i < 5; i++) { // 0 1 2 3 4 (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); } } function btn3 () { for (var i = 0; i < 5; i++) { // 5 (function() { setTimeout(function() { console.log(i); }, i * 1000); })(i); } } function btn4 () { for (var i = 0; i < 5; i++) { // 0 1 2 3 4 setTimeout((function(i) { console.log(i); })(i), i * 1000); } } function btn5 () { setTimeout(function() { // 2 3 5 4 1 console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for( var i=0 ; i<10000 ; i++ ) { i == 9999 && resolve(); } console.log(3); }).then(function() { console.log(4); }); console.log(5); } </script> </head> <body> <button onclick="btn1()">setTimeout1</button> <button onclick="btn2()">setTimeout2</button> <button onclick="btn3()">setTimeout3</button> <button onclick="btn4()">setTimeout4</button> <button onclick="btn5()">setTimeout5</button> </body> </html>

異步、作用域、閉包