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

util.isObject は既に deprecated

util パッケージには isObject 、 isFunction といった引数に渡した値が何なのかをチェックする便利関数がありますが、既に Node v4 から deprecated です。

deprecated になっている util.isXXX 系一覧

  • util.isObject
  • util.isFunction
  • util.isArray
  • util.isBuffer
  • util.isDate
  • util.isNull
  • util.isNullOrUndefined
  • util.isError
  • util.isNumber
  • util.isPrimitive
  • util.isRegExp
  • util.isString
  • util.isSymbol
  • util.isUndefined

代替手段

基本的には typeof もしくは instanceof を使って下さい。
ArrayBuffer に関しては Array.isArrayBuffer.isBuffer を使って下さい。 isPrimitive とかの複合的なものに関しては代替は無いです。 typeof を組み合わせて自分で作って下さい。

Deprecated になった経緯

今は昔、 io.js 時代に起きたことです。

util.isObjectがわかりにくいのではないか?という issue が立ち上がります。経緯となったのは下記のコードです。

var f = function(){}
util.isObject(f) // false

ここで議論になったのは「関数は object なのかどうか」です。
Node.js の過去の実装では util.isObject はこうなってます。

arg !== null && typeof arg === 'object'

functiontypeof では object にならないので、このままでは false です。

どっちが正しいのでしょうか?結論から言うと、 ECMAScriptの仕様 に書いてあります。

ECMAScript の Type は、 undefined, null, string, symbol, number, boolean, objectのみ掲載されています。つまり、 functionobject の1つという解釈が一般的』 です。

これらの解釈を受けてunderscorelodash の実装は下記のとおりで、関数でも isObjecttrue になります。

function isObject(value) {
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}

で、これは確かに問題である、 util.isObject を直したほうが良さそうだ、という事になりました。

しかし、 util.isObject という関数は既にリリースされており、動きを変えてしまうと影響を受けるライブラリも多いだろうということで折衷案として動きを変えずに deprecated で手を打とうという事になりました。

Node.js のような広く使われているライブラリの場合はこういう動き1つ変えるのにも大変です。 この手の話が多いため、 Node.js に新しい utility を付けたいという意見も多いのですが、一時期は本当に慎重でした。 npm で解決できるようなものに関しては npm にまかせてコアに追加するものに関しては本当に必要なものだけにしようという話も多かったです。この考え方を Less is More と言います。

ちなみに最近追加されたutilityで言うと、 util.isDeepStrictEqual ですが、よく追加されたなぁと思いました。