console.log是異步的嗎?

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

<!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"web

難道console.log是異步的?瀏覽器

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

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

這正是咱們所指望的結果。code

爲何會這樣?htm

由於代碼在運行的時候控制檯沒有打開對象

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

在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,然而早就被修復了。

相關文章
相關標籤/搜索