18
7

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 1 year has passed since last update.

JavaScriptでのオブジェクト比較をどうするか

Posted at

はじめに

オブジェクト同士の比較をするときに、「あ〜普通に等価演算子使えばいいじゃん」と思っていて思うような結果が返って来なかったことがありました。
オブジェクトの比較をどうするか、自分用メモです。

比較するオブジェクト

interface BaseObject {
  id: number;
  name: string;
  language: string;
  isWoman: boolean | null;
}

const objectA: BaseObject = {
  id: 1,
  name: "hoge",
  language: "jpn",
  isWoman: true,
};

const objectB: BaseObject = {
  id: 1,
  name: "hoge",
  language: "jpn",
  isWoman: true,
};

BaseObjectをベースとした二つのオブジェクトobjectAとobjectBを作ります。
この段階で、「はいはい同じオブジェクトね」と考えobjectA === objectBがtrueであるものとして実装を進めていました。笑

なぜ同じじゃないのか

objectA === objectBがfalseになることはわかった、でもなんで?
見かけ上一緒じゃん!!と思っていた私。ではそもそもなぜ同じじゃないのか

objectAとobjectBは異なるアドレスを持っているから。
objectAはアメリカで作られているからアメリカの文化を持ってる。
逆にobjectBは日本で作られているから日本の文化を持っているイメージです。

なので、objectAとobjectBは表面上は一緒かもしれないけど、参照は違うって感じかな。と個人的なイメージですが。
参考サイトは図解されていてわかりやすいので、私のイメージ話は捨て去りこちらを参考にすると良いかもしれません。

比較演算子が使えない!じゃあどうやって比較する

JSONを使う

JSON.stringfy()で文字列にして比較する。

console.log(JSON.stringify(objectA) === JSON.stringify(objectB)); //true

ただ、JSON.stringfy()を使う場合はオブジェクトの中身の順序も同じでなければtrueにならない。
例えばobjectBのプロパティの順番を変えてみます。nameを一番上に、次にid がくるようなオブジェクトにします。

const objectA: BaseObject = {
  id: 1,
  name: "hoge",
  language: "jpn",
  isWoman: true,
};

const objectB: BaseObject = {
  name: "hoge",
  id: 1,
  language: "jpn",
  isWoman: true,
};
console.log(JSON.stringify(objectA) === JSON.stringify(objectB)); //false

配列以外のオブジェクトのプロパティでは、特定の順番で文字列化されることは保証されていません。文字列化された同じオブジェクトの中でプロパティの順番に依存しないようにしてください。MDN

同じ名前の同じ値のプロパティを持つオブジェクトであっても、異なる文字列に変換され得るということです。順番が異なっていたら、変換される文字列も異なります。

lodashのisEqualを使う

JSON.stringfy()で順番考えるのは手間ですし、機能的なバグも起こりやすくなるかと思います。
そこでlodashのisEqualを使う方法があります。

lodashはJavaScriptで使用されるユーテリティライブラリです。

ユーティリティライブラリとは「配列操作」「オブジェクト操作」「数値操作」といった様々な機能をまとめて提供しているライブラリのことです。

簡潔に言うとlodashには便利な関数がたくさんあるよってことです。
isEqualはオブジェクトのキー内の順序を考慮せずにオブジェクトが等いかどうかをチェックします。

_.isEqual(objectA, objectB);
// => true
 
objectA === objectB;
// => false

記述が少なくて済みますし、もっと安全かなと思います。実務ではこの方法を採用しました
使い方や導入方法は公式に記載されています。lodash

18
7
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
18
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?