請對你的console保持懷疑態度

事情是在最近的一次開發中發現一個詭異的問題,前端在操做某個對象時,發如今chrome下console出來的值和預期的結果不一致,而後就debugger看了一下卻發現結果是對的。屢次驗證後發現debugger和console的值不一致,因而小小的探索了一番。


很少說上代碼:javascript

var obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]    
console.log(obj)    
obj.shift()    
console.log(obj)
按照正常理解,你確定會以爲what? 這麼簡單的code能有什麼問題?我猜你會說結果是這樣
//第一個console [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]
//第二個console [{ 2: 2 }, { 3: 3 }, { 4: 4 }]複製代碼

一切彷佛都在乎料之中,卻又每每超乎尋常,那咱們來看看實際的效果吧
前端



what?本切圖仔多年的切圖經驗失效了???js的執行不是同步的?代碼的執行順序不是從右到左,從上到下????java


一時間有點沒有頭緒。那麼先打個debugger看看吧。chrome

結果以下:segmentfault


結果一切正常。因而陷入懵逼狀態。。。。。數組


懵了2s,而後開始尋找問題根源,在確認代碼沒有寫錯,瀏覽器沒有緩存等問題後開始嘗試以下:瀏覽器

test1:  嘗試將var改爲const,控制檯輸出同上,排除變量定義問題。

const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]    
console.log(obj)    
obj.shift()    
console.log(obj)

複製代碼

test2: 嘗試將obj裏的值由複合數據類型改爲基本數據類型

const obj = [1, 2, 3, 4]    
console.log(obj)    
obj.shift()    
console.log(obj)複製代碼

控制檯輸出:
緩存


console出來的結果也對了,那麼基本能夠肯定問題是出在數據類型上。並且基本數據類型是OK的,那麼就是複合數據類型的問題了。聯想到複合數據類型的引用屬於地址引用,開始設想是地址引用形成了數據污染的問題,開始繼續嘗試bash


test2-1:嘗試修改原數組以前將原數組備份一份

const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]    
const obj1 = obj.slice(0)    
console.log(obj1)    
obj.shift()    
console.log(obj)複製代碼

控制檯輸出:異步


結果彷佛是跟想象中的差差差差很少吧,但又感受哪裏怪怪的。繼續嘗試


test2-2:既然基礎數據類型是能夠的,那何不不對象的值改爲基礎數據類型

const obj = [{ 1: 1 }, { 2: 2 }, { 3: 3 }, { 4: 4 }]    
console.log(JSON.stringify(obj))    
obj.shift()    
console.log(JSON.stringify(obj))複製代碼

控制檯輸出:


輸出的結果是對了,貌似仍是有點麻煩。


經過幾回嘗試,大體確認了問題所在,開始尋找問題的根源。

功夫不負有心人,好歹是面向搜索引擎的切圖仔,貌似找到了一丟丟線索:

資料來源:segmentfault.com/a/119000001…

如下內容徹底引自:《你不知道的javascript中卷》第二部分異步和性能 1.1 異步控制檯部分

並無什麼規範或一組需求指定console.* 方法族如何工做——它們並非JavaScript 正式的一部分,
而是由宿主環境(請參考本書的「類型和語法」部分)添加到JavaScript 中的。所以,不一樣的瀏覽器和JavaScript
環境能夠按照本身的意願來實現,有時候這會引發混淆。尤爲要提出的是,在某些條件下,某些瀏覽器的console.log(..)
 並不會把傳入的內容當即輸出。出現這種狀況的主要緣由是,在許多程序(不僅是JavaScript)中,I/O 是很是
低速的阻塞部分。因此,(從頁面/UI 的角度來講)瀏覽器在後臺異步處理控制檯I/O 可以提升性能,這時用戶甚
至可能根本意識不到其發生。

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


結論:經過一次詭異的問題,發現了一個以前不多注意到的一個點。吃一塹長一智,日常開發中仍是要多注意,遇到問題了要細心調試查找,雖然可能暫時一頭霧水,可是探索的過程纔是樂趣所在啊。

相關文章
相關標籤/搜索