国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

調試時經常使用的console.log()的同步和異步問題

Coly / 1702人閱讀

摘要:最近幫助一個同學在調試問題的時候,的輸出真的讓我詫異了一把,因為它竟然會出現異步輸出的情況,因而誤導了我們的判斷,找錯了方向,耽誤了很多時間,所以這里記錄一下遇到的這個問題,加深印象。但調試對象時,最好還是使用打斷點這樣的方式來調試更好。

最近幫助一個同學在調試問題的時候,console.log()的輸出真的讓我詫異了一把,因為它竟然會出現異步輸出的情況,因而誤導了我們的判斷,找錯了方向,耽誤了很多時間,所以這里記錄一下遇到的這個問題,加深印象。

問題現象:

正常輸出:

異常輸出:

我們可以發現,異常輸出的時候,沒展開的時候,顯示的name值是Tom,點擊箭頭展開對象里的name則是Jack,而且,此時的輸出值Jack執行語句,明顯是在賦值語句obj.per.name = "Jack"之前調用的,展開的時候,卻變成了Jack,明顯有些異常,是不是很神奇?我剛遇到這個問題的時候,也是懵逼狀態的。

為什么會出現這個異常輸出呢?

異常出現原因分析

在分析之前,我們得知道一點,JS中對象是引用類型,每次使用對象時,都只是使用了對象在堆中的引用。

當我們在使用obj.per.name = "Jack"改變了對象的屬性值時,它在堆中name的值也變成了"Jack",而當我們不展開對象看的時候,console.log打印的是對象當時的快照,所以我們看到的name屬性值是沒改變之前的"Tom",展開對象時,它其實是重新去內存中讀取對象的屬性值,所以當我們展開對象后看到的name屬性值是Jack

瀏覽器或者可以說是開發者工具為什么會有這樣的表現?

這個問題在《你不知道的javascript中卷》第二部分異步和性能1.1節異步控制臺部分有提及:

There is no specification or set of requirements around how the console.* methods work -- they are not officially part of JavaScript, but are instead added to JS by the hosting environment (see the Types & Grammar title of this book series).
So, different browsers and JS environments do as they please, which can sometimes lead to confusing behavior.
In particular, there are some browsers and some conditions that console.log(..) does not actually immediately output what it"s given. The main reason this may happen is because I/O is a very slow and blocking part of many programs (not just JS). So, it may perform better (from the page/UI perspective) for a browser to handle console I/O asynchronously in the background, without you perhaps even knowing that occurred.

翻譯:

并沒有什么規范或一組需求指定console.* 方法族如何工作——它們并不是JavaScript 正式的一部分,而是由宿主環境(請參考本書的“類型和語法”部分)添加到JavaScript 中的。因此,不同的瀏覽器和JavaScript 環境可以按照自己的意愿來實現,有時候這會引起混淆。
尤其要提出的是,在某些條件下,某些瀏覽器的console.log(..) 并不會把傳入的內容立即輸出。出現這種情況的主要原因是,在許多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。所以,(從頁面/UI 的角度來說)瀏覽器在后臺異步處理控制臺I/O 能夠提高性能,這時用戶甚至可能根本意識不到其發生。

書中還了個例子:

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(..)。
結論

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95327.html

相關文章

  • JavaScript是如何工作:事件循環異步編程崛起+ 5種使用 async/await 更

    摘要:事件循環從回調隊列中獲取并將其推入調用堆棧。執行從調用堆棧中移除從調用堆棧中移除快速回顧值得注意的是,指定了事件循環應該如何工作,這意味著在技術上它屬于引擎的職責范圍,不再僅僅扮演宿主環境的角色。 此篇是 JavaScript是如何工作的第四篇,其它三篇可以看這里: JavaScript是如何工作的:引擎,運行時和調用堆棧的概述! JavaScript是如何工作的:深入V8引擎&編寫...

    Honwhy 評論0 收藏0
  • 現代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺將顯示回調地獄通常,回調只能由一個異步函數調用。更多資源使更友好規范使用異步函數簡化異步編碼旅程異步編程是一項在中無法避免的挑戰。 JavaScript經常聲稱是_異步_。那是什么意思?它如何影響發展?近年來這種方法有何變化? 請思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數語言都處理每...

    shadowbook 評論0 收藏0
  • 現代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺將顯示回調地獄通常,回調只能由一個異步函數調用。更多資源使更友好規范使用異步函數簡化異步編碼旅程異步編程是一項在中無法避免的挑戰。 JavaScript經常聲稱是_異步_。那是什么意思?它如何影響發展?近年來這種方法有何變化? 請思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數語言都處理每...

    oujie 評論0 收藏0
  • 現代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺將顯示回調地獄通常,回調只能由一個異步函數調用。更多資源使更友好規范使用異步函數簡化異步編碼旅程異步編程是一項在中無法避免的挑戰。 JavaScript經常聲稱是_異步_。那是什么意思?它如何影響發展?近年來這種方法有何變化? 請思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數語言都處理每...

    anquan 評論0 收藏0
  • javascript之異步函數

    摘要:所以增加了異步函數,提高了代碼可讀性,對不太熟悉的人而言,幫助就更大了。因為異步函數去掉了所有回調。這就是此代碼有效的原因它和以下一樣代碼更易讀正如上面示例所見,與回調和代碼相比,異步函數代碼看起來非常簡單。 這篇文章詳細講解了JavaScript中的異步函數。 JavaScript中的異步代碼在很短的時間內從回調發展為Promise,再到ES2017的異步函數,現在我們可以像編寫同步...

    WrBug 評論0 收藏0

發表評論

0條評論

Coly

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<