console.log()眼見不爲實的緣由

全部結果的運行環境都爲Chrome,不一樣的瀏覽器運行結果可能不一樣

眼見不爲實

第一行打出來是Obj,點開後發現竟然有屬性a且值爲"賦值後"
第二行打印出屬性a的值,倒是Undefinedjavascript

let test = {}
        console.log(test)
        console.log(test.a)
        test.a="賦值後"

image

深刻分析console.log(Object)

爲何會出現眼見不爲實的狀況

若是咱們打印一個對象,chrome默認會省略具體信息,只顯示一個Object,這是引用的快照,而不是快照的內容
你不點開,引擎是不會去這個引用的地址去取內容的java

let obj = {
            a:"a",
            b:{
                bb:'bb'
            },
            timeOut:"now"
        }
        console.log(obj)
        console.log(obj.a)
        console.log(JSON.stringify(obj))
        
        obj.a="a修改後"
        obj.b.bb="bb修改後"
        
        console.log(obj)

image

當咱們點擊這個object展開的時候,chrome會從新獲取這些引用的值
但當咱們點擊object去展開的時候,代碼已經執行完了,因而從新獲取的是修改過的值
實際上至關於一種懶加載,這也是爲何你能夠在控制檯無限查看Object的prototype了。 chrome

image

setTimeout驗證Chrome取值模式

下面的代碼會有兩種不一樣輸出,只取決於你點開打印出來的Object的時間瀏覽器

let obj = {
            timeOut:"now"
        }
        
        console.log(obj)
        console.log(obj)
        console.log(obj.timeOut)
        
        
        setTimeout(()=>{
            obj.timeOut="五秒後"
        },5000)

第一種狀況爲你不等待,直接點擊展開兩個Object,timeOut都爲now,即便你等了5後折上再展開去拉取值,值不再會改變了,chrome應該會存儲此次的拉取過的數據,不會再改變了,
image異步

第二種狀況是再展開第二個Object的時候我等了5秒鐘再展開
image工具

獲取準確的對象信息-console.log(JSON.stringify(obj))

這種方式能強制打出如今的結果,
把對象序列化到一個字符串中,以強制執行一次「快照」性能

console.log是異步或是同步的說法是不許確的

這不是異步和同步的問題,console並非JavaScript提供的對象,而是由宿主環境(請參考本書的「類型和語法」部分)添加到JavaScript 中的。這具體到不一樣的瀏覽器,好比Chrome中是由Devtool的控制檯提供,Firefox中是由Firebug的控制檯提供。
imagespa

《你不知道的javascript中卷》中的部分具體說明

並無什麼規範或一組需求指定console.* 方法中如何工做——它們並非JavaScript 正式
的一部分,而是由宿主環境(請參考本書的「類型和語法」部分)添加到JavaScript 中的。所以,不一樣的瀏覽器和JavaScript 環境能夠按照本身的意願來實現,有時候這會引發混淆。prototype

尤爲要提出的是,在某些條件下,某些瀏覽器的console.log(..) 並不會把傳入的內容當即輸出。出現這種狀況的主要緣由是,在許多程序(不僅是JavaScript)中,I/O 是很是低速的阻塞部分。因此,(從頁面/UI 的角度來講)瀏覽器在後臺異步處理控制檯I/O 可以提升性能,這時用戶甚至可能根本意識不到其發生。3d

下面這種情景不是很常見,但也可能發生,從中(不是從代碼自己而是從外部)能夠觀察到這種狀況:
PS:能夠試試這個

var a = {
    index: 1
};
// 而後
console.log( a ); // ??
// 再而後
a.index++;

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

多數狀況下,前述代碼在開發者工具的控制檯中輸出的對象表示與指望是一致的。

可是,這段代碼運行的時候,瀏覽器可能會認爲須要把控制檯I/O 延遲到後臺,在這種狀況下,
等到瀏覽器控制檯輸出對象內容時,a.index++ 可能已經執行,所以會顯示{ index: 2 }。

到底何時控制檯I/O 會延遲,甚至是否可以被觀察到,這都是遊移不定的。

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

若是遇到這種少見的狀況,最好的選擇是在JavaScript 調試器中使用斷點,而不要依賴控制檯輸出。次優的方案是把對象序列化到一個字符串中,以強制執行一次「快照」,好比經過JSON.stringify(..)。

相關文章
相關標籤/搜索