console.log是異步的嗎?


今晚我加的一個前端群里有人問了這樣一個問題,下面這段代碼在Chrome中運行:

<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="UTF-8">
    <title></title>
    </head>
    <body>
    <script>
            var a = {name: '1'};
            console.log(a);
            a.name = '2';
            console.log(a);
    </script>
    </body>
</html>

打開控制台后,卻發現運行結果是這樣的:

Object
    name: "2"
    __proto__: Object
Object
    name: "2"
    __proto__: Object

這個結果不符合我們所期望的第一個輸出是name: "1"

難道console.log是異步的?

可是當我將那段JavaScript代碼粘貼到控制台直接運行,或是打開控制台后刷新一遍網頁,運行結果就會變成:

Object {name: "1"}
Object {name: "2"}

這正是我們所期望的結果。

為什么會這樣?

因為代碼在運行的時候控制台沒有打開

首先明確一點,a所儲存的是一個引用類型值的地址,所有對a的操作都會具體到這個地址所對應的那個對象上。其次,console並不是JavaScript提供的對象,而是瀏覽器的控制台提供的。這具體到不同的瀏覽器,比如Chrome中是由Devtool的控制台提供,Firefox中是由Firebug的控制台提供。

在Chrome中,console.log在控制台打開后才起作用,也就是說,當你打開控制台時,console.log才會將之前被傳進去的參打印出來。
那么問題來了,在上述代碼中,傳進console.log中的參是一個地址,當代碼執行完畢后,打開控制台,console.log開始起作用,那么它打印出的實際上是已經做完全部處理后的對象。這就相當於這樣的執行順序:

var a = {name: '1'};
a.name = '2';
console.log(a);
console.log(a);

如果是打開控制台再運行代碼,那么console.log是直接起作用的,代碼會順序執行,所以所看到的結果是符合期望的。

那么該如何解決這個問題?只能在執行的過程中創建新對象來曲線救國了:

var a = {name: '1'};
console.log(JSON.parse(JSON.stringify(a)));
a.name = '2';
console.log(JSON.parse(JSON.stringify(a)));

這相當於幫瀏覽器對要被改變的對象存了個快照。

當然,只要你開着控制台來執行代碼,那么是不會出現這樣的問題的。

最后我認為這不是個BUG,相反這是個節省運算資源的行為。無論控制台是否打開console.log都起作用是十分不妥的。

開着控制台還會出現不符合期望的結果才是BUG,然而早就被修復了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM