javascriptのconsole.logについてメモ

質問して教えてもらったのでメモ。

JavaScriptの基本の「image changer を追加する」にあるコードを動かした。

var myImg = document.querySelector('img')

myImg.onclick = function () {
  var mySrc = myImg.getAttribute('src')

  if (mySrc === 'images/firefox-icon.png') {
    console.log(myImg) // firefox-icon2.png ...①
    console.log(mySrc) // firefox-icon.png ...②
    myImg.setAttribute('src', 'images/firefox2.png') // ...③
  } else {
    myImg.setAttribute('src', 'images/firefox-icon.png')
  }
}

③を実行する前に①と②の中身をconsole.logで確認したところ、予想では①②の両方ともfirefox-icon.pngが表示されると思ったのが、①だけfirefox-icon2.pngが表示された。

console.logはコンソールを確認した時点での値を表示する

console.logする対象がオブジェクトのとき、コンソールに表示される値はコンソールを開いて確認した時点での値になる。typeofで確認すると、①はオブジェクトで②は文字列だった。

例①

var obj={"bool":true}

console.log(obj);

setTimeout(function(){
    obj.bool=false;
}, 5000);

このコードを実行してから「5秒以内にコンソールを確認」するとtrueが表示され、「5秒後にコンソールを確認」するとfalseが表示される。これは5秒以内の時点だとconsole.logしているobjの中身がまだtrueだからで、5秒後にコンソールを開いて確認したときにはsetTimeoutが実行されてobjのboolがfalseに変更されているからコンソールの表示内容も変わる。

※正確には「5秒後にsetTimeoutの処理が実行される」のではなく「5秒後にsetTimeoutが実行キューに登録されてそのあとに処理が実行される」
参考:JavaScript を学ぶ際に一番重要なのに、誤解されがちな setTimeout 系の概念

例②

var a = new Array(100, 300, 200)

a.push(500)
console.log(a) // [100, 300, 200, 500] ...①
a.splice(1, 2, 800, 1000)
console.log(a) //  [100, 800, 1000, 500] ...②

このコードを「コンソールを最初から表示した状態で実行」したとき、①②の結果はコメントの通りになる。「console.logを実行してからコンソールを開いて確認」した場合は①②の結果は両方とも[100, 800, 1000, 500]になる。これはコードの処理が全て終わった時点でのaの値を表示しているからこの結果になる。

console.logより下に値を書き換えたり代入するコードがあったとしても、コンソールを確認するまでにその変更が実行された場合は、コンソールに表示される値は変更後の値になる。これはオブジェクトに対して起こる現象で、プリミティブな値(文字列・数値 etc)では起こらない(たぶん)。一番最初のコードの②の結果がfirefox-icon.pngだったのは、②の型がプリミティブな値(文字列)だったから。