那些前端工做中遇到的坑(01)

前段時間接手一個老項目(jQuery+React混在一塊)的遷移工做,除了用React重寫一些老頁面(這種至少是本身寫的,內心有數,調起來也省心),剩下的就是將原有的React遷到新倉庫裏,複製!粘貼!改路徑!完事!是個體力活。javascript

你覺得這樣就結束了?一大堆bug在等着,整整改了半個月,雖然都是些小問題,但成天被測試釘來釘去仍是蠻頭疼的。java

如今來講說今天的主角吧,這是一個不起眼的問題,最初發現的時候很讓人摸不着頭腦。node

part one數組

const res = request(url);
console.log(res);   // { stat: 'ok', data: { value: 1, childs: [1, 2, 3] } }
複製代碼

上面的代碼很普通,可是打開控制檯的Network去看這個接口的返回結果是:{ stat: 'ok', data: { value: 1, children: [1, 2, 3] } },你沒有看錯,返回的數據中是children,而console.log打印出來的是childs,是否是很難以想象?接下來咱們逐一排查問題。瀏覽器

part twobash

const res = request(url);
console.log(JSON.stringify(res));   // { stat: 'ok', data: { value: 1, children: [1, 2, 3] } }
console.log(res);   // { stat: 'ok', data: { value: 1, childs: [1, 2, 3] } }
複製代碼

這裏咱們把res轉成字符串再輸出,和直接輸出對比發現轉成字符串後的結果是和接口返回的結果同樣的,都是children。看到這裏相信有很多小夥伴已經清楚是怎麼回事了,但應該也有部分同窗腦子裏全是問號了(好比當時的我)。 異步

若是光是靠這些線索,確實還沒發定位問題。那咱們進一步探索,既然出問題的的是 res,那就順藤摸瓜,找到使用他的地方。而後就發現了這段代碼:

res.data.children = res.data.childs;
delete res.data.childs;
複製代碼

原來是爲了換字段,直接操做了源數據,而對象,數組都是引用類型的,so...性能

那難道console.log難道是異步執行的嗎,否則代碼順序執行的話前面輸出的結果應該是對的呀?測試

這麼說其實不許確,咱們把一樣的代碼換個方式執行,好比node.js:ui

而後跟在瀏覽器中執行對比一下:

這樣就很清晰了,問題在於瀏覽器控制檯的輸出機制,但爲何要這麼設計呢?在網上查閱了一番後,得出的結論是:若是順序執行console.log(輸出的內容較大,層級較深),可能會形成阻塞,影響用戶體驗,因此瀏覽器在後臺異步處理了console.log

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

而經過JSON.stringify轉成字符串再輸出至關於給res拍了一次快照(記錄了他最初的樣子),後面再操做該對象也不會影響到這個字符串(你操做對象關我字符串什麼事)。

問題搞清楚了,下面要考慮的就是怎麼解決以及之後如何避免。

歸根到底就是一句話:

不要操做源數據!

不要操做源數據!

不要操做源數據!

使用以前深拷貝一下,可使用最簡單粗暴的JSON.parse(JSON.stringify(res))

雞湯:坑踩多了沒關係,反正後面還多着呢

相關文章
相關標籤/搜索