2
1

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 5 years have passed since last update.

JavaScriptで、オブジェクトに値を紐付けたい

Last updated at Posted at 2018-01-27

JavaScriptで、キーと値の対応を取るような構造を考えていたときに、少し悩むことがありました。

他言語と比較して

RubyやJavaでは、Hashのキーには文字列や数値だけでなく、任意のオブジェクトを入れることができます。そして、「オブジェクトとしての同一性」以外に「内容の同一性」を考える、別次元での等値判定が用意してあります。

一方で、JavaScriptには連想配列を実現する手段として、「Object」と「Map」があります。詳しい記事があるので中身は省略すると、

  • Object…キーは文字列しか使えない、toString__proto__のように特殊な動作をするキーもある
  • Map…オブジェクト型についてはオブジェクトの同一性判定しかない

という状況なので、(JavaScriptにそもそもオブジェクトが「値として同一」だということを判定する仕組み自体ないですが)「値として同一」なオブジェクトをキーに処理を行いたい、となると、なかなかうまく行きません。

JSON化の罠

幸い、今回キーにしたいオブジェクトは、「Object」「文字列」「配列」「数値」「ブール値」「null」を組み合わせた、JSONにできるオブジェクトなので、「JSONをキーにすれば適当な方法で管理できるんじゃないか」とも、いったんは思いました。

ただ、RubyやPHPでは連想配列の順序が保証されるのに対して、JavaScriptもJSONも、キーの順序は不定となっています。つまり、「キーも値もすべて同じ」オブジェクトがあったとして、それをJSON化しても、JSONがどんな順序になるのか制御する方法もないわけで、単純な手法では同じJSONを生成することができません。

// falseとなる可能性が高いけど、それも保証されない
console.log(JSON.stringify({foo: '1', bar: 2}) === JSON.stringify({bar: 2, foo: '1'}));

探せばあった

そこで行き詰まっていたところ、npmにjson.sortifyというものがありました。名前のとおり、キーをソートしてJSONを生成するルーチンで、「A deterministic version of JSON.stringify」、つまり同じキーと値の組み合わせなら必ず同じJSON文字列を生成する、とありました。今回やりたいことにぴったりです。

…とおもったら、JavaScriptとしての規定がないからわざわざ入れようというはずなのに、「先に入れたキーが先に出力される」というJavaScriptエンジンの挙動に依存していて、「これはどうなんだ」という気分になってしまいました。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?