Node.js
Node.jsDay 18

util.inspect 便利

Node.js Advent Calendar が埋まってなかったので、代わりに細かすぎて伝わりにくいTips入れていきます。

util.inspect

object の文字列化をするための関数です。まぁまぁ便利なのですが、あまり使われてないシリーズです。先日公開した %o 便利という記事でも若干出しましたが、もうちょい詳しく解説してみます。

%o 便利

記事でも触れましたが、 util.inspect%o フォーマッターを使った時に内部で呼ばれている関数です。

const util = require('util')
const obj = { foo: 'bar', bar: 123, baz: true }
obj.hoge = obj
const str = util.inspect(obj) 
console.log(str) // '{ foo: 'bar', bar: 123, baz: true, hoge: [Circular] }'

console.log('hello %o', obj) // hello { foo: 'bar', bar: 123, baz: true, hoge: [Circular] }

JSON valid な文字列ではないので、 JSON.parse しようとしてもエラーになります。

一番使うのはやはり debug print の時ですね。 %o で大体のケースは抑えられているのですが、 %o では深さが4までのオブジェクトしか print されません。もっとオブジェクトの構造が複雑なケースの場合は util.inspect を使いましょう。

util.inspectのオプション

おさらいです。

  • showHidden: Enumerable じゃないオブジェクトを表示したいときには true にします。デフォルトは false
util.inspect([1,2,3], { showHidden: true }) // '[ 1, 2, 3, [length]: 3 ]'
  • showProxy: Proxyのオブジェクトや関数を表示するかどうか、デフォルトは false
const handler = {
    get: function(target, name){
        return name
    }
}
const p = new Proxy({}, handler)
util.inspect(p, {showProxy: true}) // 'Proxy [ {}, { get: [Function: get] } ]'
  • depth: オブジェクトを表示する深さ、デフォルトは深さ 2 全部表示したければ null にします。
  • colors: ANSIカラーを当てるかどうか、 true なら勝手に Node.js が決めた色でカラーリングされます。デフォルトは false
util.inspect([1,2,3], {colors: true})
// '[ \u001b[33m1\u001b[39m, \u001b[33m2\u001b[39m, \u001b[33m3\u001b[39m ]'
  • customInspect: v6.6.0 で入った機能。カスタム表示を許可するかどうか、デフォルトは true 。カスタム表示機能に関しては後述
  • maxArayLength: 配列の要素を何個まで表示するか。デフォルトは 100 全て表示したければ null
  • breakLength: どのくらいの長さで改行するか。デフォルトは 6060 なのは歴史上の理由から。 Infinity にすれば改行しない。

util.inspect.custom

debug print を prototype を拡張することでカスタマイズすることもできます。

const util = require('util')

const Dog = function(name, age) {
  this.name = name
  this.age = age
}

Dog.prototype[util.inspect.custom] = function(depth, options) {
  if (!this.name) {
    // color は https://nodejs.org/api/util.html#util_customizing_util_inspect_colors 参照
    return options.stylize(`Name: No-Name, Age: ${this.age}`, 'null')
  }

  return options.stylize(`Name: ${this.name}, Age: ${this.age}`, 'special')
}

console.log(util.inspect(new Dog('pochi', 12), { colors: true }))
console.log(util.inspect(new Dog('', 0), { colors: true }))

image.png

image.png

あんまりカスタム表示は使いませんが、デバッグ表示の際わざわざ表示してほしくないものを隠す時とかに使います。

const util = require('util')

class CustomBuffer {
  constructor(buf) {
    this.target = Buffer.from(buf)
  }

  [util.inspect.custom](depth, options) {
    const label = options.stylize(`[CustomBuffer]`, 'special')
    return label + 'length: ' + this.target.length
  }
}

util.inspect(new CustomBuffer('foo')) 
// 通常時はこうなるCustomBuffer { target: <Buffer 66 6f 6f> }
// Custom表示しているとこうなる [CustomBuffer]length: 3