全部結果的運行環境都爲Chrome,不一樣的瀏覽器運行結果可能不一樣
第一行打出來是Obj,點開後發現竟然有屬性a且值爲"賦值後"
第二行打印出屬性a的值,倒是Undefinedjavascript
let test = {} console.log(test) console.log(test.a) test.a="賦值後"
若是咱們打印一個對象,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)
當咱們點擊這個object展開的時候,chrome會從新獲取這些引用的值
但當咱們點擊object去展開的時候,代碼已經執行完了,因而從新獲取的是修改過的值
實際上至關於一種懶加載,這也是爲何你能夠在控制檯無限查看Object的prototype了。 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應該會存儲此次的拉取過的數據,不會再改變了,異步
第二種狀況是再展開第二個Object的時候我等了5秒鐘再展開工具
這種方式能強制打出如今的結果,
把對象序列化到一個字符串中,以強制執行一次「快照」性能
這不是異步和同步的問題,console並非JavaScript提供的對象,而是由宿主環境(請參考本書的「類型和語法」部分)添加到JavaScript 中的。這具體到不一樣的瀏覽器,好比Chrome中是由Devtool的控制檯提供,Firefox中是由Firebug的控制檯提供。spa
並無什麼規範或一組需求指定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(..)。