3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptでブラウザのコンソールにconsole.log出力する時は参照型に注意しましょう

Posted at

概要

ブラウザでJavaScriptを実行している時にconsole.logに参照型のデータを渡して出力すると期待通りに出力されない場合があります。その再現手順と回避策を記します。

ソースコード

今回使用するソースコードは以下の2ファイルです。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>console-log-sample</title>
</head>
<body>
  <script src="./main.js"></script>
</body>
</html>
main.js
'use strict';

class Name {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}
class Human {
  constructor(name, age, address1, address2) {
    this.name = name;
    this.age = age;
  }
}

const name = new Name('太郎', '佐藤');
const human = new Human(name, 25);
console.log(human); // firstName が 太郎, lastName が 佐藤, age が 25 と出力して欲しい

human.name = new Name('次郎', '鈴木');;
human.age = 30;
console.log(human); // firstName が 次郎, lastName が 鈴木, age が 30 と出力して欲しい

ブラウザ(Chrome)で実行した場合の出力結果

index.html をブラウザで表示したときのコンソール出力結果は画像の通りです。

chrome_console_01.png

ageは期待通りに出力できていますね。nameの中身を確認するために展開してみましょう。

chrome_console_02.png

展開してみると、1つ目のconsole.log結果と2つ目のconsole.log結果が同じ値になっています。どうやら後から代入した値が出力されているようですね。

なぜこんな現象が発生するのでしょうか。これについてはMDNのドキュメントに記載がありました。

console.log() - Web API | MDN

出力する JavaScript オブジェクトのリスト。各オブジェクトの文字列表現が記述順で出力されます。
Chrome や Firefox の比較的新しいバージョンを使っているなら注意が必要です。
これらのブラウザーで記録されるのはオブジェクトへの参照です。そのため、 console.log() を呼び出した時点でのオブジェクトの「値」が表示されるのではなく、内容を見るために開いた時点での値が表示されます。

つまり、console.logを呼び出した時点の値ではなく、ブラウザで展開した時の値を出力しているということになります。

回避策

回避策についてもMDNのドキュメントに記載がありました。

console.log(obj) を使わず、 console.log(JSON.parse(JSON.stringify(obj))) を使用してください。
これにより、ログを記録した瞬間の obj の値を確実に見ることができます。こうしないと、多くのブラウザーでは値が変化したときに常に更新されるライブビューになります。これは望むことではないかもしれません。

それでは、MDNのドキュメント通りにmain.jsを書き換えてみましょう。
(赤色の部分を削除し、代わりに緑色の部分で挿入します。)

main.js
'use strict';

class Name {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}
class Human {
  constructor(name, age, address1, address2) {
    this.name = name;
    this.age = age;
  }
}

const name = new Name('太郎', '佐藤');
const human = new Human(name, 25);
- console.log(human); // firstName が 太郎, lastName が 佐藤, age が 25 と出力して欲しい
+ console.log(JSON.parse(JSON.stringify(human)));

human.name = new Name('次郎', '鈴木');;
human.age = 30;
- console.log(human); // firstName が 次郎, lastName が 鈴木, age が 30 と出力して欲しい
+ console.log(JSON.parse(JSON.stringify(human)));

main.jsを書き換えた後に、再度ブラウザで開いてみます。

chrome_console_03.png

期待通りの出力結果になりましたね。

まとめ

参照型データをconsole.logで出力する時は、console.log(JSON.parse(JSON.stringify(obj)))を使うと期待通りの出力結果が得られます。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?