#Overview
過去にバグになってしまったものを忘れないよう書き留めておくシリーズです。
今回の題材はMapです。以下は私が最初にさらりと書いたコードです。
これを基に❌な部分を修正していきます。
const map = new Map();
if (!map["1"]) {
map["1"] = "⭕";
}
for(const {key, value} of map) {
console.log(`key:${key}, value:${value}`);
}
#Target reader
- この結果がわからない方
#Prerequisite
- JavaScriptを一通り理解している
- 今回はChromeで実行したが、Node.js等、環境によって出力結果が異なることがあることに注意。
#Body
少しだけ言い訳をしたい
いつもはJSONでファイル出力することが多いため、どうしてもそのまま出力できるObjectを利用することが多い。
そんな折、ファイル出力ないものがあったので、久しぶりにMapを使ったらずいぶん忘れていただけ。
今はもう大丈夫なんで
##答え合わせ
正解はこうなる。
何も出ないが正解
そもそも、MapはMapにあるメソッドを使って値を扱い必要がある。
Map オブジェクトに対してオブジェクトプロパティを設定すると正しく動作しますが、混乱を催すことが考えられます。
要するに、Object的な扱いもできる故に、Mapにデータ入れたと思ったらハマりますよってことで。
詳しくは上記URL参照のこと。
ということで、Object的な扱いを一つ一つ是正していく。
const map = new Map();
if (!map.has("1")) { // ❌ !map["1"]
map.set("1", "⭕"); // ❌ map["1"] = "⭕";
}
for(const {key, value} of map.entries()) {
console.log(`key:${key}, value:${value}`);
}
これで正しくMapのデータ構造にデータを入れれたはず…答えはこうだ。
何も出ない
よく見ると、of map
ではなくof map.entries()
でkey-value
のペアを受け取らないといけなかった!
const map = new Map();
if (!map.has("1")) { // ❌ !map["1"]
map.set("1", "⭕"); // ❌ map["1"] = "⭕";
}
for(const {key, value} of map.entries()) { // ❌ map
console.log(`key:${key}, value:${value}`);
}
これで正しくMapのデータ構造にデータを入れれたはず…答えはこうだ。
> "key:undefined, value:undefined"
値がない
そういえば、map.entries()
ってkey-value
のペアだからオブジェクトから取り出しではない!
const map = new Map();
if (!map.has("1")) { // ❌ !map["1"]
map.set("1", "⭕"); // ❌ map["1"] = "⭕";
}
for(const [key, value] of map.entries()) { // ❌ map, ❌ {key, value}
console.log(`key:${key}, value:${value}`);
}
これで正しくMapのデータ構造にデータを入れれたはず…答えはこうだ。
> "key:1, value:⭕"
動いた
ちなみに、以下のように、値のセットをObjectとして処理し、存在チェックをMapで処理すると…
const map = new Map();
map["1"] = "❌";
if (!map.has("1")) {
map.set("1", "⭕");
}
for(const [key, value] of map.entries()) {
console.log(`key:${key}, value:${value}`);
}
> "key:1, value:⭕"
本来なら❌が出力され、⭕での上書きを防止するはずがそれを防げないという厄介なバグに発展するので要注意。
#Conclusion
Map
はObject
と似ているように見えるが、使い方が異なるのでうろ覚えでの使用には注意!
特に存在チェックとセットメソッドを混在して利用する等すると泥沼。