成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

調(diào)試時(shí)經(jīng)常使用的console.log()的同步和異步問(wèn)題

Coly / 1767人閱讀

摘要:最近幫助一個(gè)同學(xué)在調(diào)試問(wèn)題的時(shí)候,的輸出真的讓我詫異了一把,因?yàn)樗谷粫?huì)出現(xiàn)異步輸出的情況,因而誤導(dǎo)了我們的判斷,找錯(cuò)了方向,耽誤了很多時(shí)間,所以這里記錄一下遇到的這個(gè)問(wèn)題,加深印象。但調(diào)試對(duì)象時(shí),最好還是使用打斷點(diǎn)這樣的方式來(lái)調(diào)試更好。

最近幫助一個(gè)同學(xué)在調(diào)試問(wèn)題的時(shí)候,console.log()的輸出真的讓我詫異了一把,因?yàn)樗谷粫?huì)出現(xiàn)異步輸出的情況,因而誤導(dǎo)了我們的判斷,找錯(cuò)了方向,耽誤了很多時(shí)間,所以這里記錄一下遇到的這個(gè)問(wèn)題,加深印象。

問(wèn)題現(xiàn)象:

正常輸出:

異常輸出:

我們可以發(fā)現(xiàn),異常輸出的時(shí)候,沒(méi)展開的時(shí)候,顯示的name值是Tom,點(diǎn)擊箭頭展開對(duì)象里的name則是Jack,而且,此時(shí)的輸出值Jack執(zhí)行語(yǔ)句,明顯是在賦值語(yǔ)句obj.per.name = "Jack"之前調(diào)用的,展開的時(shí)候,卻變成了Jack,明顯有些異常,是不是很神奇?我剛遇到這個(gè)問(wèn)題的時(shí)候,也是懵逼狀態(tài)的。

為什么會(huì)出現(xiàn)這個(gè)異常輸出呢?

異常出現(xiàn)原因分析

在分析之前,我們得知道一點(diǎn),JS中對(duì)象是引用類型,每次使用對(duì)象時(shí),都只是使用了對(duì)象在堆中的引用。

當(dāng)我們?cè)谑褂?b>obj.per.name = "Jack"改變了對(duì)象的屬性值時(shí),它在堆中name的值也變成了"Jack",而當(dāng)我們不展開對(duì)象看的時(shí)候,console.log打印的是對(duì)象當(dāng)時(shí)的快照,所以我們看到的name屬性值是沒(méi)改變之前的"Tom",展開對(duì)象時(shí),它其實(shí)是重新去內(nèi)存中讀取對(duì)象的屬性值,所以當(dāng)我們展開對(duì)象后看到的name屬性值是Jack。

瀏覽器或者可以說(shuō)是開發(fā)者工具為什么會(huì)有這樣的表現(xiàn)?

這個(gè)問(wèn)題在《你不知道的javascript中卷》第二部分異步和性能1.1節(jié)異步控制臺(tái)部分有提及:

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.

翻譯:

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

書中還了個(gè)例子:

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

我們通常認(rèn)為恰好在執(zhí)行到console.log(..) 語(yǔ)句的時(shí)候會(huì)看到a 對(duì)象的快照,打印出類似于{ index: 1 } 這樣的內(nèi)容,然后在下一條語(yǔ)句a.index++ 執(zhí)行時(shí)將其修改,這句的執(zhí)行會(huì)嚴(yán)格在a 的輸出之后。

多數(shù)情況下,前述代碼在開發(fā)者工具的控制臺(tái)中輸出的對(duì)象表示與期望是一致的。但是,這段代碼運(yùn)行的時(shí)候,瀏覽器可能會(huì)認(rèn)為需要把控制臺(tái)I/O 延遲到后臺(tái),在這種情況下,等到瀏覽器控制臺(tái)輸出對(duì)象內(nèi)容時(shí),a.index++ 可能已經(jīng)執(zhí)行,因此會(huì)顯示{ index: 2 }。

到底什么時(shí)候控制臺(tái)I/O 會(huì)延遲,甚至是否能夠被觀察到,這都是游移不定的。

所以如果在調(diào)試的過(guò)程中遇到對(duì)象在console.log(..) 語(yǔ)句之后被修改,可你卻看到了意料之外的結(jié)果,要意識(shí)到這可能是這種I/O 的異步化造成的。

書中建議:

如果遇到這種少見的情況,最好的選擇是在JavaScript 調(diào)試器中使用斷點(diǎn),而不要依賴控制臺(tái)輸出。次優(yōu)的方案是把對(duì)象序列化到一個(gè)字符串中,以強(qiáng)制執(zhí)行一次“快照”,比如通過(guò)JSON.stringify(..)。
結(jié)論

由此可見,console.log打印出來(lái)的內(nèi)容并不是一定百分百可信的內(nèi)容。一般對(duì)于基本類型number、string、boolean、null、undefined的輸出是可信的。但對(duì)于Object等引用類型來(lái)說(shuō),則就會(huì)出現(xiàn)上述異常打印輸出。

所以對(duì)于一般基本類型的調(diào)試,調(diào)試時(shí)使用console.log來(lái)輸出內(nèi)容時(shí),不會(huì)存在坑。但調(diào)試對(duì)象時(shí),最好還是使用打斷點(diǎn)(debugger)這樣的方式來(lái)調(diào)試更好。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/95327.html

相關(guān)文章

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

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

    Honwhy 評(píng)論0 收藏0
  • 現(xiàn)代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺(tái)將顯示回調(diào)地獄通常,回調(diào)只能由一個(gè)異步函數(shù)調(diào)用。更多資源使更友好規(guī)范使用異步函數(shù)簡(jiǎn)化異步編碼旅程異步編程是一項(xiàng)在中無(wú)法避免的挑戰(zhàn)。 JavaScript經(jīng)常聲稱是_異步_。那是什么意思?它如何影響發(fā)展?近年來(lái)這種方法有何變化? 請(qǐng)思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數(shù)語(yǔ)言都處理每...

    shadowbook 評(píng)論0 收藏0
  • 現(xiàn)代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺(tái)將顯示回調(diào)地獄通常,回調(diào)只能由一個(gè)異步函數(shù)調(diào)用。更多資源使更友好規(guī)范使用異步函數(shù)簡(jiǎn)化異步編碼旅程異步編程是一項(xiàng)在中無(wú)法避免的挑戰(zhàn)。 JavaScript經(jīng)常聲稱是_異步_。那是什么意思?它如何影響發(fā)展?近年來(lái)這種方法有何變化? 請(qǐng)思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數(shù)語(yǔ)言都處理每...

    oujie 評(píng)論0 收藏0
  • 現(xiàn)代JS中流程控制:詳解Callbacks 、Promises 、Async/Await

    摘要:控制臺(tái)將顯示回調(diào)地獄通常,回調(diào)只能由一個(gè)異步函數(shù)調(diào)用。更多資源使更友好規(guī)范使用異步函數(shù)簡(jiǎn)化異步編碼旅程異步編程是一項(xiàng)在中無(wú)法避免的挑戰(zhàn)。 JavaScript經(jīng)常聲稱是_異步_。那是什么意思?它如何影響發(fā)展?近年來(lái)這種方法有何變化? 請(qǐng)思考以下代碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數(shù)語(yǔ)言都處理每...

    anquan 評(píng)論0 收藏0
  • javascript之異步函數(shù)

    摘要:所以增加了異步函數(shù),提高了代碼可讀性,對(duì)不太熟悉的人而言,幫助就更大了。因?yàn)楫惒胶瘮?shù)去掉了所有回調(diào)。這就是此代碼有效的原因它和以下一樣代碼更易讀正如上面示例所見,與回調(diào)和代碼相比,異步函數(shù)代碼看起來(lái)非常簡(jiǎn)單。 這篇文章詳細(xì)講解了JavaScript中的異步函數(shù)。 JavaScript中的異步代碼在很短的時(shí)間內(nèi)從回調(diào)發(fā)展為Promise,再到ES2017的異步函數(shù),現(xiàn)在我們可以像編寫同步...

    WrBug 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<