for(var i=0;i<=3;i++){ setTimeout(function() { console.log(i) }, 10);}
答案:打印4次4
這道題涉及了異步、作用域、閉包
settimeout是異步執行,10ms后往任務隊列里面添加一個任務,只有主線上的全部執行完,才會執行任務隊列里的任務,當主線執行完成后,i是4,所以此時再去執行任務隊列里的任務時,i全部是4了。對於打印4次是:
因為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.