JavaScript オブジェクトを比較する 4 つの方法

JavaScript オブジェクトを比較する 4 つの方法

序文

JavaScript でプリミティブ値を比較するのは非常に簡単です。厳密な等価演算子など、利用可能な等価演算子のいずれかを使用します。

'a' === 'c'; // => 偽
1 === 1; // => 真

ただし、オブジェクトには構造化されたデータがあるため、比較はより困難になります。この記事では、JavaScript でオブジェクトを適切に比較する方法を学習します。

参考比較

JavaScript には、値を比較するための 3 つの方法が用意されています。

  • 厳密な等価演算子 ===
  • 緩い等価演算子 ==
  • Object.is() 関数

上記のいずれかの方法を使用してオブジェクトを比較する場合、比較された値が同じオブジェクト インスタンスを参照している場合にのみ、比較は true と評価されます。これは参照等価性です。

オブジェクト hero1 と hero2 を定義して、参照の等価性が実際にどのように機能するかを見てみましょう。

定数ヒーロー1 = {
  名前: 「バットマン」
};
定数hero2 = {
  名前: 「バットマン」
};

hero1 === hero1; // => 真
ヒーロー1 === ヒーロー2; // => 偽

hero1 == hero1; // => 真
ヒーロー1 == ヒーロー2; // => 偽

Object.is(hero1, hero1); // => true
Object.is(hero1, hero2); // => false

両方のオペランドが同じオブジェクト インスタンス hero1 を参照するため、hero1 === hero1 は true と評価されます。

一方、hero1 と hero2 は異なるオブジェクト インスタンスであるため、hero1 === hero2 は false と評価されます。

興味深いことに、hero1 オブジェクトと hero2 オブジェクトの内容は同一です。両方のオブジェクトに、値が「Batman」である name プロパティがあります。ただし、hero1 === hero2 は、同じ構造のオブジェクトを比較する場合でも false と評価されます。

参照の等価性は、オブジェクトの内容ではなく参照を比較する場合に便利です。しかし、多くの場合、オブジェクトの実際の内容、つまりプロパティとその値を比較する必要があります。

次に、オブジェクトの内容に基づいてオブジェクトを比較する方法を見てみましょう。

手動比較

オブジェクトをコンテンツ別に比較する最も簡単な方法は、プロパティを読み取って手動で比較することです。

たとえば、2 つのヒーロー オブジェクトを比較する特別な関数 isHeroEqual() を記述してみましょう。

関数 isHeroEqual(オブジェクト1, オブジェクト2) {
  object1.name === object2.name を返します。
}

定数ヒーロー1 = {
  名前: 「バットマン」
};
定数hero2 = {
  名前: 「バットマン」
};
定数hero3 = {
  名前: 「ジョーカー」
};

isHeroEqual(hero1, hero2); // => true
isHeroEqual(hero1, hero3); // => false

isHeroEqual() は両方のオブジェクトの name プロパティにアクセスし、その値を比較します。

比較するオブジェクトに何らかのプロパティがある場合は、isHeroEqual() のような比較関数を記述することをお勧めします。このタイプの関数はパフォーマンスが良好です。比較には少数のプロパティ アクセサーと等価演算子のみが関与します。

手動比較ではプロパティを手動で抽出する必要がありますが、単純なオブジェクトの場合は問題になりません。ただし、大きなオブジェクト (または構造が不明なオブジェクト) を比較する場合は、大量の定型コードが必要になるため、便利ではありません。

それでは、オブジェクトの浅い比較がどのように役立つかを見てみましょう。

浅い比較

浅い比較を使用してオブジェクトをチェックする場合は、両方のオブジェクトのプロパティのリストを取得し (Object.keys() を使用)、それらのプロパティ値が等しいかどうかを確認する必要があります。

次のコードは浅い比較の実装です。

関数 shallowEqual(オブジェクト1, オブジェクト2) {
  定数keys1 = Object.keys(object1);
  定数keys2 = Object.keys(object2);

  キー1の長さがキー2の長さと等しい場合
    false を返します。
  }

  for (let index = 0; index < keys1.length; index++) {
    定数val1 = object1[keys1[index]];
    val2 = object2[keys2[index]];
    (val1 !== val2)の場合{
      false を返します。
    }
  }

  true を返します。
}

関数内では、keys1 と keys2 はそれぞれ object1 と object2 のプロパティの名前を含む配列です。

for ループを使用してキーを反復処理し、object1 と object2 の各プロパティを比較します。

浅い比較を使用すると、多くのプロパティを持つオブジェクトの等価性を簡単にチェックできます。

定数ヒーロー1 = {
  名前:「バットマン」
  本名:「ブルース・ウェイン」
};
定数hero2 = {
  名前:「バットマン」
  本名:「ブルース・ウェイン」
};
定数hero3 = {
  名前: 「ジョーカー」
};

shallowEqual(hero1, hero2); // => true
shallowEqual(hero1, hero3); // => false

shallowEqual(hero1, hero2)は、hero1とhero2のオブジェクトが

属性(nameとrealName)は同じで、値も同じです。

一方、hero1 と hero3 はプロパティが異なるため、shallowEqual(hero1, hero3) は false を返します。

しかし、JavaScript のオブジェクトはネストできます。この場合、浅い比較はうまく機能しません。

以下は、ネストされたオブジェクトを持つオブジェクトに対して浅い比較チェックを実行します。

定数ヒーロー1 = {
  名前:「バットマン」
  住所:
    都市: 'ゴッサム'
  }
};
定数hero2 = {
  名前:「バットマン」
  住所:
    都市: 'ゴッサム'
  }
};

shallowEqual(hero1, hero2); // => false

今回は、2 つのオブジェクト hero1 と hero2 の内容が同じであるにもかかわらず、shallowEqual(hero1, hero2) は false を返します。

これは、ネストされたオブジェクト hero1.address と hero2.address が異なるオブジェクト インスタンスであるために発生します。したがって、浅い比較では、hero1.address と hero2.address は 2 つの異なる値とみなされます。

ネストされたオブジェクトの問題を解決するには、詳細な比較が必要です。

徹底比較

ディープ比較は、シャロー比較に似ていますが、プロパティにオブジェクトが含まれている場合は、ネストされたオブジェクトに対して再帰的なシャロー比較が実行される点が異なります。

ディープ比較の実装を見てみましょう。

関数 deepEqual(オブジェクト1, オブジェクト2) {
  定数keys1 = Object.keys(object1);
  定数keys2 = Object.keys(object2);

  キー1の長さがキー2の長さと等しい場合
    false を返します。
  }

  for (let index = 0; index < keys1.length; index++) {
    定数val1 = object1[keys1[index]];
    val2 = object2[keys2[index]];
    定数 areObjects = isObject(val1) && isObject(val2);
    if (areObjects && !deepEqual(val1, val2) || 
        !areObjects && val1 !== val2) {
      false を返します。
    }
  }

  true を返します。
}

関数isObject(オブジェクト) {
  戻りオブジェクト != null && typeof object === 'object';
}

13 行目 areObjects && !deepEqual(val1, val2) チェックされたプロパティがオブジェクトになると、再帰呼び出しが開始され、ネストされたオブジェクトも等しいかどうかが検証されます。

次に、deepEquality() を使用してオブジェクトをネストされたオブジェクトと比較します。

定数ヒーロー1 = {
  名前:「バットマン」
  住所:
    都市: 'ゴッサム'
  }
};
定数hero2 = {
  名前:「バットマン」
  住所:
    都市: 'ゴッサム'
  }
};

deepEqual(hero1, hero2); // => true

ディープ比較関数は、ネストされたオブジェクト hero1.address と hero2.address の等価性を含め、hero1 と hero2 が同じプロパティと値を持っているかどうかを正しく判断します。

オブジェクトの詳細な比較には、Node の組み込みユーティリティ モジュールの isDeepStrictEqual(object1, object2) または lodash ライブラリの _.isEqual(object1, object2) を使用することをお勧めします。

要約する

参照等価性 (===、==、または Object.is() を使用) は、オペランドが同じオブジェクト インスタンスであるかどうかを判断するために使用されます。

オブジェクトの等価性を手動でチェックするには、プロパティ値を手動で比較する必要があります。このタイプのチェックでは、属性を比較するために手動でコーディングする必要がありますが、簡単なので便利です。

比較するオブジェクトに多くのプロパティがある場合、またはオブジェクトの構造が実行時に決定される場合は、浅いチェックを使用する方がよい方法です。

比較するオブジェクトにネストされたオブジェクトがある場合は、詳細な比較チェックを実行する必要があります。

以上がJavaScriptオブジェクトを比較する4つの方法の詳細です。JavaScriptの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • js で 2 つのオブジェクトを比較する方法の例
  • jsは2つの別々の配列またはオブジェクトの等価性を比較します
  • JS で 2 つの Json オブジェクトが等しいかどうかを比較する方法は? サンプル コード
  • 2つのJsonオブジェクトの値を比較して等しいかどうかを確認するJSの例の詳細な説明
  • jsオブジェクトの比較
  • JavaScript オブジェクト比較実装コード
  • JavaScriptオブジェクトの4つのメソッドの詳細な説明

<<:  JS で列挙をシミュレートする方法

>>:  デスクトップ仮想化を実現するために Hyper-V を展開する手順 (グラフィック チュートリアル)

推薦する

MySQLが大量のデータを処理する際にクエリ速度を最適化するいくつかの方法

実際に参加したプロジェクトでは、MySQL テーブルのデータ量が数百万に達すると、通常の SQL ク...

Centos8 システムの VMware インストール チュートリアル図 (中国語グラフィカル モード)

目次1. ソフトウェアとシステムイメージ2. 仮想マシンを作成する3. CentOS8をインストール...

テーブル適応とオーバーフローのいくつかの設定の詳細な説明

1. テーブル リセットの 2 つのプロパティ: ①border-collapse: collaps...

Vue ルーターにパラメータを渡すときにページを更新するとパラメータが失われる問題に対処する方法

目次概要方法1: params経由でパラメータを渡す方法2: クエリを通じてパラメータを渡す方法3:...

Vueはマーキースタイルのテキストの水平スクロールを実装します

この記事では、マーキースタイルのテキストの水平スクロールを実現するためのVueの具体的なコードを参考...

一般的なDockerコマンドの詳細な説明

1. ヘルプコマンド1. 現在のDockerバージョンを表示する docker バージョン2. イメ...

HTMLおよびJSPページがキャッシュされ、Webサーバーから再取得されるのを防ぎます。

ユーザーがログアウトした後、ブラウザの戻るボタンがクリックされると、Web アプリケーションは保護さ...

Vuex でゲッターとアクションを使用するための追加手順

予備的注釈1.Vue2.xとVue3.xの違い: Vue 3.x にはヘルパー関数はありません。 V...

js が CSS 属性 (値) のサポートを決定して通知する状況の分析

新しい CSS 機能を使用する場合、その互換性は常に考慮されます。おそらく、その互換性、どのブラウザ...

HTML でテーブルを分割および結合する (colspan、rowspan)

このコードは水平マージを示しています。 <!DOCTYPE html PUBLIC "...

IE6/7 で絶対配置された要素が不可解に消えたりブロックされたりする問題を解決する方法

1. 絶対配置レイヤーの隣接フローティング レイヤーの幅が親レイヤーの幅と等しくなく、フロートがクリ...

純粋な CSS でマークダウンの自動番号付けを実装するサンプル コード

問題の起源私がタイトルの番号付けの問題に初めて注目したのは、学部の論文を書いていた頃まで遡ります。当...

Vueはタブルーティング切り替えコンポーネントのメソッド例を実装します

序文この記事では、vue に付属している vue-router.js ルーティングを使用してページン...

MySQLカバーインデックスの詳しい説明

コンセプトインデックスにクエリ要件を満たすすべてのデータが含まれている場合、それはカバーリング イン...

MySQL クエリの最適化: クエリが遅い原因と解決策

開発に携わっている友人、特に MySQL に関係のある友人は、非常に遅い MySQL クエリに遭遇す...