👌
【JavaScript】よく使う連想配列処理備忘録
JavaScriptの連想配列(オブジェクト)に対してよく使うコレクション関数・メソッドを、チートシート的にまとめていきます。
Object.assign()
- 処理内容
複数のオブジェクトをマージする。第一引数に新しいオブジェクトを指定すれば非破壊。
const user = { id: 1, name: "Taro" };
const info = { age: 20, city: "Tokyo" };
const merged = Object.assign({}, user, info);
console.log(merged); // { id: 1, name: "Taro", age: 20, city: "Tokyo" }
- 戻り値
マージされたオブジェクト(第一引数と同一)
※破壊的(第一引数に既存オブジェクトを指定した場合)、非破壊的(新しいオブジェクトを指定した場合)
Object.entries() / Object.fromEntries()
- 処理内容
Object.entries(obj) はオブジェクトの自身の列挙可能なプロパティを [key, value] の配列で返す。
Object.fromEntries(iterable) はその逆で、[key, value] ペアの反復可能オブジェクト(配列や Map など)から新しいオブジェクトを作る。
両者を組み合わせるとオブジェクトを配列操作(map/filter 等)で変換して復元できる。
const user = { id: 1, name: "Taro", age: 20 };
// entries: オブジェクト -> ペア配列
const entries = Object.entries(user);
console.log(entries); // [["id",1],["name","Taro"],["age",20]]
// 配列操作で変換(例:age を文字列化)
const transformed = entries.map(([k, v]) => [k, k === "age" ? String(v) : v]);
console.log(transformed); // [["id",1],["name","Taro"],["age","20"]]
// fromEntries: ペア配列 -> オブジェクト
const newObj = Object.fromEntries(transformed);
console.log(newObj); // { id: 1, name: "Taro", age: "20" }
// filter の例:特定キーだけ残す
const filtered = Object.fromEntries(
Object.entries(user).filter(([k]) => k !== "id")
);
console.log(filtered); // { name: "Taro", age: 20 }
- 戻り値
- Object.entries → 配列(キー順はオブジェクトの列挙順)
- Object.fromEntries → 新しいオブジェクト(非破壊)
Object.freeze() / Object.isFrozen()
- 処理内容
Object.freeze(obj) はオブジェクトを浅く凍結し、プロパティの追加・削除・書き換えや属性変更を禁止する(破壊的)。
Object.isFrozen(obj) は凍結されているかを判定する。
対比ポイント
- 役割:
- Object.freeze → オブジェクトを凍結(アクション)
- Object.isFrozen → 凍結されているかを調べる(クエリ)
- 深さ: 両方とも浅い前提。ネストしたオブジェクトは自動で凍結されない。
- 挙動: 非 strict では変更試行は無視されるが、strict モードでは TypeError が投げられる。
- 破壊性: Object.freeze はオブジェクト状態を変更し、元に戻せない。
const obj = { a: 1, b: { c: 2 } };
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true
console.log(Object.isFrozen(obj.b)); // false(ネストは凍結されていない)
obj.a = 10;
console.log(obj.a); // 1¥
}());
- 戻り値
Object.freeze → 凍結したオブジェクト
Object.isFrozen → boolean - 補足ポイント
- 凍結は浅い:ネストオブジェクトを凍結したい場合は再帰的に Object.freeze を呼ぶ(Deep freeze)。
- 一度凍結すると元に戻せない(アンフリーズ不可)。
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach((k) => {
const v = obj[k];
if (v && typeof v === 'object' && !Object.isFrozen(v)) {
deepFreeze(v);
}
});
return obj;
}
Object.hasOwn() / Object.prototype.hasOwnProperty()
- 処理内容
Object.hasOwn(obj, prop) は ES2022 で追加された静的メソッドで、指定オブジェクトが自身のプロパティとして prop を持つか安全に判定する。
Object.prototype.hasOwnProperty は従来のインスタンスメソッドだが、オブジェクト側で上書きされていると使えない場合がある(その場合は call を使う)。
const user = { id: 1, name: "Taro" };
// ES2022+
console.log(Object.hasOwn(user, "name")); // true
// 古い書き方(注意あり)
console.log(user.hasOwnProperty("name")); // true(通常はOK)
// hasOwnProperty を上書きされた場合の例
const obj = {
hasOwnProperty: () => false,
foo: "bar"
};
console.log(obj.hasOwnProperty("foo")); // false ← 問題
console.log(Object.prototype.hasOwnProperty.call(obj, "foo")); // true ← 安全な呼び方
console.log(Object.hasOwn(obj, "foo")); // true ← 一番安全で推奨
-
戻り値
boolean(非破壊) -
補足
Object.hasOwn が使えない古い環境では次のように代用できる。
const hasOwn = Object.hasOwn || ((obj, prop) =>
Object.prototype.hasOwnProperty.call(obj, prop)
);
Object.keys
- 処理内容
オブジェクトの全てのキーを配列で取得する。
const user = { id: 1, name: "Taro", age: 20 };
const keys = Object.keys(user);
console.log(keys); // ["id", "name", "age"]
- 戻り値
配列(非破壊)
Object.seal() / Object.isSealed()
- 処理内容
Object.seal(obj) はオブジェクトを浅く封印し、プロパティの追加・削除を禁止して既存プロパティの configurable を false にする。
既存プロパティの値の書き換えは writable が true なら許される。Object.isSealed(obj) は封印されているかを判定する。
const obj = { a: 1, b: 2 };
Object.seal(obj);
console.log(Object.isSealed(obj)); // true
obj.c = 3; // 追加は無視(非 strict)または TypeError(strict)
delete obj.a; // 削除は無視(非 strict)または TypeError(strict)
obj.b = 20; // 既存プロパティの書き換えは許可される(writable の場合)
console.log(obj); // { a:1, b:20 }
freeze()との比較
- 役割:
- Object.seal → プロパティの追加/削除を禁止し、プロパティの設定可能性(configurable)を無効化する(既存プロパティの書き換えは許可される場合がある)
- Object.freeze → プロパティの追加/削除/書き換えすべてを禁止する(より厳格)
- 挙動の違い:
- seal は既存の writable プロパティの値変更を許す(freeze は許さない)
- 両者とも浅い(ネストオブジェクトは自動で処理されない)
- 破壊性: Object.seal はオブジェクトの状態を変更する(アンシール不可)
- strict モード: 追加/削除/削除試行は非 strict では無視され、strict では TypeError を投げる
実用メモ
-
既存のプロパティを残しつつ外部からの追加/削除だけを防ぎたい場合は seal を使う(freeze より緩やか)。
-
深く封印したい場合は再帰処理で個々のネストオブジェクトに対して seal を適用する必要がある。
-
一度 seal すると元に戻せないので、変更が将来必要な場合はコピーしてから操作する。
-
戻り値
- Object.seal → 封印したオブジェクト(同一参照)
- Object.isSealed → boolean
Object.values()
- 処理内容
オブジェクトの全ての値を配列で取得する。
const user = { id: 1, name: "Taro", age: 20 };
const values = Object.values(user);
console.log(values); // [1, "Taro", 20]
- 戻り値
配列(非破壊)
for...in ループ
- 処理内容
オブジェクトの全てのキーを列挙して処理できる。
const user = { id: 1, name: "Taro", age: 20 };
for (const key in user) {
console.log(key, user[key]);
}
// id 1
// name Taro
// age 20
-
戻り値
なし(ループ内で処理) -
補足
列挙時にプロトタイプチェーンのプロパティも含まれるので hasOwnProperty などでフィルタすると安全。ループ内でオブジェクトを直接変更すると破壊的になる。
まとめ
- ほとんどの関数は非破壊的です。
-
Object.assignやfor...inループ内での操作は場合によって破壊的になるので注意しましょう。
Discussion