JavaScript經典面試題

for(var i = 1; i <= 3;i++){
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    },0)
    console.log("這是下面的i:"+i)
}

輸出: 在這裏插入圖片描述
OK!爲啥輸出結果是這樣子的呢?

所用知識點:作用域,閉包,異步

相信大家對for循環已經很瞭解了,應該只是對setTimeout有點陌生

setTimeout(function(){
    console.log(2)
},0)
console.log(1)

輸出 1,2

由此可見,我們使用setTimeout的時候是一種異步機制。setTimeout有兩個參數,第一個是函數,第二個是執行的時間間隔值,默認毫秒。異步指的是當函數在執行這個事件時,把函數的參數放在事件對列中,等主程序執行完,然後再執行這個事件。體現在我們的例子中,就是當程序執行到setTimeout時,會將setTimeout中的參數放在主程序執行的事件隊列裏,當主程序執行完畢之後,纔會執行setTimeout中的內容。
當setTimeout的時間爲0代表等待主程序執行完之後再執行異步的程序,若不爲o則代表執行主程序的同時開始計時,等時間到了之後再執行程序。


接下來分析一下代碼運行流程:

i = 1
console.log("這是下面的i:"+i)           // 1
i++						 
console.log("這是下面的i:"+i)           // 2 
i++
console.log("這是下面的i:"+i)           // 3
i++
console.log("這是上面的i:"+i)			// 4
console.log("這是上面的i:"+i)			// 4
console.log("這是上面的i:"+i)			// 4

那麼到這一步應該對這個理解了吧。
還有一個問題就是作用域。如果我們執行的程序是這樣子的

for(let i = 1; i <= 3;i++){
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    },0)
    console.log("這是下面的i:"+i)
}

輸出:
這是下面的i:1
這是下面的i:2
這是下面的i:3
這是上面的i:1
這是上面的i:2
這是上面的i:3

變量提升:使用var時候聲明變量是函數作用域,作用在全局,在預解析時會將變量提升到函數頂部,在這裏也就是全局的頂部,而let聲明的變量是塊級作用域,在預解析時候會把變量提升在for循環的第一行。
代碼分析:

for(let i = 1; i <= 3;i++){
	let i = 圓括號中的值
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    },0)
    console.log("這是下面的i:"+i)
}

// 執行流程
// 每次輸出i的值,i都會根據作用域鏈去找他的值。
// 第一次
	let i = 1
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    },0)
    console.log("這是下面的i:"+i)
    i++
// 第二次
    let i = 2
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    },0)
    console.log("這是下面的i:"+i)
    i++
// 第三次
	let i = 3
	setTimeout(function(){console.log("這是上面的i:"+i)},0)
	console.log("這是下面的i:"+i)
	i++
--------------------
然後在這裏呢,我們會看到setTimeout中的i依次爲1,2,3  只是在每次執行的時候都將setTimeout
中的值放在了主程序之後,所以我們會輸出1,2,3,1,2,3這樣的結果

關於let和var在for循環中的表現可以參考以下鏈接:

https://blog.csdn.net/wlk2064819994/article/details/79772388

當然如果我們想要讓setTimeout中的值先輸出也可以,將函數改爲立即執行函數

for(var i = 1; i <= 3;i++){
    setTimeout(function(){
        console.log("這是上面的i:"+i)
    }(i),0)								// 立即執行函數
    console.log("這是下面的i:"+i)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章