console.log()打印顯示異常的原因分析

日常開發中我們經常使用console.log的輸出來輔助查看我們所控制的變量的值,有些時候能夠正常,而有些時候的輸出卻在我們的意料之外,到底是什麼原因呢?

JS中對象是引用類型,每次使用對象時,都只是使用了對象在堆中的引用。而當我們不展開對象看的時候,console.log打印的是對象當時的快照,所以我們看到的對象的屬性值並沒有改變,展開對象時,它其實是重新去內存中讀取對象的屬性值,所以當我們展開對象後看到的屬性值與未展開之前是不一樣的。

在某些條件下,某些瀏覽器的console.log(..) 並不會把傳入的內容立即輸出。出現這種情況的主要原因是,在許多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。所以,(從頁面/UI 的角度來說)瀏覽器在後臺異步處理控制檯I/O 能夠提高性能,這時用戶甚至可能根本意識不到其發生。

我們通常認爲恰好在執行到console.log(..) 語句的時候會看到a 對象的快照,打印出類似於{ index: 1 } 這樣的內容,然後在下一條語句a.index++ 執行時將其修改,這句的執行會嚴格在a 的輸出之後。

多數情況下,前述代碼在開發者工具的控制檯中輸出的對象表示與期望是一致的。但是,這段代碼運行的時候,瀏覽器可能會認爲需要把控制檯I/O 延遲到後臺,在這種情況下,等到瀏覽器控制檯輸出對象內容時,a.index++ 可能已經執行,因此會顯示{ index: 2 }。

到底什麼時候控制檯I/O 會延遲,甚至是否能夠被觀察到,這都是遊移不定的。

所以如果在調試的過程中遇到對象在console.log(..) 語句之後被修改,可你卻看到了意料之外的結果,要意識到這可能是這種I/O 的異步化造成的。

因此,console.log打印出來的內容並不是一定百分百可信的內容。一般對於基本類型number、string、boolean、null、undefined的輸出是可信的。但對於Object等引用類型來說,則就會出現上述異常打印輸出。

所以對於一般基本類型的調試,調試時使用console.log來輸出內容時,不會存在坑。但調試對象時,最好還是使用打斷點(debugger)這樣的方式來調試更好。

發佈了19 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章