Code Fix

上級

オブジェクトのキーは数値でも文字列に変換される(1と"1"は同じキー)

JavaScriptのオブジェクトのプロパティキーは、Symbolを除きすべて文字列として扱われます。数値のキーを指定しても内部的には文字列に変換されるため、数値の1と文字列の"1"は同じキーとして衝突します。

なぜエラーが出ないのか

出力: 1
(エラーなし)
JavaScriptは何も報告しません。文法として正しいためです
出力: 1
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  const votes = {};
 2  votes[1] = "apple";
 3  votes["1"] = "banana";
           ^
 4  console.log(Object.keys(votes).length);
出力: 1期待: 2 (エラーにはなりません)

votes["1"]はvotes[1]と同じキーを指します。別々の投票のつもりで書いても、片方がもう片方を上書きしてキーは1つのままです。

直し方: "1" を 2 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  const cache = {};
 2  cache[10] = "x";
 3  cache["10"] = "y";
            ^
 4  console.log(Object.keys(cache).length);
出力: 1期待: 2 (エラーにはなりません)

cache["10"]はcache[10]と同じキーになります。数値と文字列のキーは区別されません。

直し方: "10" を 20 にします。

この問題を解いてみる →

パターン3

 1  const inventory = {};
 2  inventory[100] = "sword";
 3  inventory["100"] = "shield";
                ^
 4  console.log(Object.keys(inventory).length);
出力: 1期待: 2 (エラーにはなりません)

inventory["100"]はinventory[100]と同一のキーとして扱われ、上書きされてキーは1つのままになります。

直し方: "100" を 200 にします。

この問題を解いてみる →

パターン4

 1  const scores = {};
 2  scores[5] = "A";
 3  scores["5"] = "B";
            ^
 4  console.log(Object.keys(scores).length);
出力: 1期待: 2 (エラーにはなりません)

scores["5"]はscores[5]と同じキーを指すため、上書きされてキーは1つのままです。

直し方: "5" を 6 にします。

この問題を解いてみる →

パターン5

 1  const map = {};
 2  map[3] = "x";
 3  map["3"] = "y";
         ^
 4  console.log(Object.keys(map).length);
出力: 1期待: 2 (エラーにはなりません)

数値と文字列のキーは区別されません。map["3"]はmap[3]と同一のキーです。

直し方: "3" を 4 にします。

この問題を解いてみる →

よくある誤解

「数値のキーと文字列のキーは別物として区別されるはず」という思い込みは誤りです。obj[1]とobj["1"]は同じプロパティを指すため、片方への代入がもう片方の値を上書きします。

実務での勘所

この制約は素のオブジェクトだけの話で、Mapを使えば回避できます。const m = new Map(); m.set(1, ...); m.set("1", ...);のように書くと、Mapは数値の1と文字列の"1"を別々のキーとして正しく区別し、2つのエントリとして保持します。この「キーの型を保持できる」という性質は、ES2015でMapが新しく言語に追加された主な動機の1つです。キーに数値やオブジェクトそのものを使いたい場面では、素のオブジェクトではなくMapを検討する価値があります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)