2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Object.fromEntriesで項目が減る理由:重複キーと数値・文字列の衝突をNode.jsで実測

2
Posted at

Object.fromEntries() に同じキーを2回渡すと、今回の例では後ろの値が残り、プロパティは一つになりました。

10月11日のgroupBy記事は戻り値の性質、今回は重複キーの衝突と変換停止が主題です。

実測環境:macOS 27.0.1/Node.js v24.22.1、2026年10月28日。ブラウザと他のNode.jsバージョンでは試していません。

同じ文字列キーは後ろの値で置き換わる

const entries = [['theme', 'light'], ['theme', 'dark']];
const result = Object.fromEntries(entries);
console.log(JSON.stringify(result));
console.log(entries.length, Object.keys(result).length);
console.log(JSON.stringify(entries));

出力:

{"theme":"dark"}
2 1
[["theme","light"],["theme","dark"]]

元の配列は変わっていません。同名のプロパティを二つ持たせられず、後の値が残りました。

後勝ちの設定上書きなら意図どおりでも、全件を残す用途には合いません。

数値1と文字列の1も、オブジェクトでは重なる

console.log(JSON.stringify(Object.fromEntries([
  [1, 'number'],
  ['1', 'string'],
])));

出力は次の一つでした。

{"1":"string"}

数値 1 は文字列のキーに変換され、"1" と重なります。Symbolやオブジェクトをキーにする入力は試していません。

Mapなら数値と文字列を区別するが、変換すると再び重なる

const map = new Map([[1, 'number'], ['1', 'string']]);
console.log(map.size, map.get(1), map.get('1'));
console.log(JSON.stringify(Object.fromEntries(map)));

出力:

2 number string
{"1":"string"}

Mapでは数値と文字列を区別できましたが、オブジェクトに変換すると一つになります。Mapでも同じ文字列キーを設定すると値が更新されます。

重複を許さないなら、入力条件を決めて変換を止める

次は「キー・値の二要素配列の配列、キーは文字列のみ」という入力条件の例です。任意の壊れた入力を扱う汎用バリデーターではありません。

function uniqueObject(pairs) {
  const seen = new Set();
  for (const [key] of pairs) {
    if (typeof key !== 'string') {
      throw new TypeError('key must be string');
    }
    if (seen.has(key)) {
      throw new Error('duplicate key: ' + key);
    }
    seen.add(key);
  }
  return Object.fromEntries(pairs);
}

try {
  uniqueObject([['theme', 'light'], ['theme', 'dark']]);
} catch (e) {
  console.log(e.message);
}
console.log(JSON.stringify(uniqueObject([
  ['theme', 'light'], ['font', 'large'],
])));

出力:

duplicate key: theme
{"theme":"light","font":"large"}

全件を残すなら、ペアの配列を保つ方法もあります。後勝ち・重複で失敗・全件保持のどれが要件かを決めます。Object.keysの件数はSymbolキーなどを含む一般の入力へそのまま広げられません。

仕様の参照先

手順はECMAScript仕様を参照。


未経験者向けの体験版を公開しています

※ 中上級者には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?