今晚我加的一個前端羣裏有人問了這樣一個問題,下面這段代碼在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,然而它早就被修復了。