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

More than 3 years have passed since last update.

やらかしJS先生がみたMapをObject的に扱ってハマった話⭕❌

Posted at

#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

少しだけ言い訳をしたい:sweat_smile:

いつもはJSONでファイル出力することが多いため、どうしてもそのまま出力できるObjectを利用することが多い。
そんな折、ファイル出力ないものがあったので、久しぶりにMapを使ったらずいぶん忘れていただけ。
今はもう大丈夫なんで:rolling_eyes:

##答え合わせ

正解はこうなる。

terminal

何も出ないが正解:joy:

そもそも、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のデータ構造にデータを入れれたはず…答えはこうだ。

terminal

何も出ない:joy:

よく見ると、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のデータ構造にデータを入れれたはず…答えはこうだ。

terminal
> "key:undefined, value:undefined"

値がない:joy:

そういえば、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のデータ構造にデータを入れれたはず…答えはこうだ。

terminal
> "key:1, value:⭕"

動いた:sob:

ちなみに、以下のように、値のセットを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}`);
}

terminal
> "key:1, value:⭕"

本来なら❌が出力され、⭕での上書きを防止するはずがそれを防げないという厄介なバグに発展するので要注意。

#Conclusion

MapObjectと似ているように見えるが、使い方が異なるのでうろ覚えでの使用には注意!
特に存在チェックとセットメソッドを混在して利用する等すると泥沼。

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