JavaScriptでネストされたオブジェクトの全プロパティ値が同一かどうかを再帰的に判定する方法
問題の概要
ネストされた(入れ子構造の)オブジェクトを受け取り、すべてのキーの値が同一であるかどうかに応じて真偽値(boolean)を返す関数――たとえば isSame()――を作成することを考えてみましょう。
ここでいう「すべてのキー」とは、末端のキーのことを指します。あるキーの値としてさらにオブジェクトがネストされている場合は、その奥まで辿っていき、最終的な値をチェックする必要があります。
例として、次のようなオブジェクトを見てみます。
const obj = {
a: 1,
b: 1,
c: {
aa: 1
}
};
この場合、すべての末端キーの値が 1 で共通しているため、関数は true を返すべきです。それでは、この問題を再帰処理を使って解いてみましょう。
実装例:再帰による解法
const obj = {
a: 1,
b: 1,
c: {
aa: 3
}
};
const allSame = (obj, value) => {
const keys = Object.keys(obj);
for(let i = 0; i < keys.length; i++){
if(typeof obj[keys[i]] === "object" &&
!Array.isArray(obj[keys[i]])){
return allSame(obj[keys[i]], value);
};
if(!value){
value = obj[keys[i]];
continue;
}
if(obj[keys[i]] !== value){
return false;
};
};
return true;
}
console.log(allSame(obj));
console.log(allSame({ a: 1, b: 1, c: { aa: 1 } }));
console.log(allSame({ a: { x: 1 }, b: 1, c: { aa: 1 } }));
console.log(allSame({ a: 1, b: 1, c: { aa: 2 } }));
実行結果
コンソールには次のように出力されます。
false true true false
コードのポイント
この関数の動作を整理すると、以下の流れになっています。
Object.keys()でオブジェクトのキー一覧を取得し、順番に走査します。- 値がオブジェクト型で、かつ配列ではない場合は、そのネストされたオブジェクトに対して自身(
allSame)を再帰的に呼び出します。 valueがまだ設定されていない場合(最初に見つかった末端の値)、その値を比較の基準として記録します。- 以降のキーの値が基準値と一致しない場合は、その場で
falseを返して処理を打ち切ります。 - 最後まで不一致がなければ
trueを返します。
なお、この実装ではネストされたオブジェクトに遭遇した時点で再帰呼び出しの結果をそのまま返すため、兄弟キーよりも先にネスト内部の値が評価されます。より厳密にオブジェクト全体のすべての分岐を検査したいケースでは、早期リターン方式から結果を蓄積していく方式へ変更することも検討するとよいでしょう。
-
JavaScriptで配列の要素を同じ配列内に複製する方法
JavaScriptでは、concat()メソッドとsort()メソッドを組み合わせることで、既存の配列の要素を同じ配列内に複製することができます。ここでは、実際に動作するサンプルコードを使って、その手順をわかりやすく解説します。 コード例 以下は、配列の要素を同じ配列内に複製するためのコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport" cont
-
【JavaScript】オブジェクトがクラスのインスタンスかどうかを判定する方法
JavaScriptでは、instanceof 演算子を使うことで、あるオブジェクトが特定のクラス(コンストラクタ関数)のインスタンスであるかどうかを簡単に判定できます。instanceof 演算子とは?instanceof 演算子は、左辺のオブジェクトが右辺に指定したコンストラクタ関数のプロトタイプチェーン上に存在するかどうかを評価し、その結果を真偽値(true / false)として返します。この仕組みを利用することで、オブジェクトがどのクラスから生成されたものなのかを実行時に動的にチェックできます。コード例以下は、ボタンをクリックしたときに student1 オブジェクトが Studen