2022/07/09

[javascript] プリミティブ型と toString()

困ったことに、JavaScript の try-catch で catch するものは Error 型とは限らないそうだ。
取りあえずログに出したかったのだが、JSON.stringify(e) で {} になったり、 e で [Object Object] になったりして、もう考えるのが面倒になってきた。
Error 型だったら、e.message と e.name はあるのだけど、ライブラリを使っていると派生したオブジェクトを返したりして、もうどうしてよいやら・・・。

Error - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Error

よく見ると、インスタンスメソッドで toString() があった。

Error - JavaScript | MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#instance_methods

Error を派生したんだったら toString() もオーバーライドしてほどほどの文字列を作るのが礼儀なんじゃなかろうか、きっとそうだ、と思い込むことにした。

 

しかし、throw が Error 型じゃなくてもよいということはプリミティブ型でもよいはずだ。
プリミティブ型はオブジェクトじゃないはずだ。
オブジェクトじゃないなら Object を継承しないので toString() を持たないかもしれない。
だったら e の型チェックしてからじゃないと toString() が使えないのか。
めんどくさい・・・。

 

と思って文字列や数字を throw したのだが、toString() で文字列として出力されていた。
なんで??

本を読んだところ、プリミティブ型は使われる際にラッパーオブジェクトが一時的に生成されるようになっているらしい。
つまり、文字列なら String型、数字なら Number型が生成される。
これらはオブジェクトなので toString() を使える、という理屈のようだ。

もしかしたら toString() などのメソッドを使う直前に生成されるのかもしれん。そっちの方が理屈に合うか。

 

それはそうと、元の問題である catch したデータをログに出した意見だが、これは昔からどうしたもんだかって話のようだ。 Error の派生についてStackoverflow のリンクが載っているくらいだから、 throw となるとさらにめんどくさそうだ。

throw - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/throw

オンラインでコードを動かせるので throw を書き換えながら試したが、 new Error(文字列) は console.log で出力できるが、単に Object として {message: 文字列} なんかを throw すると [object Object] になる。
じゃあ console.log で JSON.stringify() したものを出せば良いのだが、 new Error() だと {} だけになる。

 

そういえば、console.log を使いたいわけでは無く、ログファイルに出力させたいので「文字列」として取得したいのを忘れていた。 console.dir が使えるという記事があったのだけど、そういうわけで今回は対象外だ。

となると、無難に toString() しておけば文字列として取得できるのか。
オブジェクトの中を全て見れば詳細な情報が確認できる場合もありそうだが、そこはもうピンポイントで調べたい場合だけとあきらめても許してくれるんじゃないだろうか。