なにこの記事&なぜ
- ES6 以降の構文で groupBy を書いた。そのときに調べたことを残す。
-
Object.groupBy() - JavaScript | MDN
- ここのサンプルコードをブラウザのコンソールにコピペしたら動かなかった(記事を書いてるときにコピペしたら動きました)のがきっかけ。
先に結論だけ教えて
- JavaScript ではデータを持たないことを示す型が
null
とundefined
に分かれている - JavaScript では連想配列に存在しないキーを指定してもエラーにならず、
undefined
を返す -
undefined
はfalse
として扱われる値のひとつ(Falsy) - 比較演算子 == は、比較する値の型が異なる場合、JavaScript内部で暗黙の型変換を行う
サンプルコード:groupBy
こちらのソースコードをご覧ください。いくつか既存の groupBy 実装を見ながら書いたものです
const inventory = [
{ name: "asparagus", type: "vegetables", quantity: 5 },
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "goat", type: "meat", quantity: 23 },
{ name: "cherries", type: "fruit", quantity: 5 },
{ name: "fish", type: "meat", quantity: 22 },
];
const key = "type";
const res = inventory.reduce((accumulator, current) => {
const index = current[key];
accumulator[index] = accumulator[index]
? [...accumulator[index], current]
: [current];
return accumulator;
}, {});
ここ読みづらくないですか?
accumulator[index] = accumulator[index]
? [...accumulator[index], current]
: [current];
- オブジェクトに存在しないキーを指定してもエラーを返さず、
undefined
を返す。- たとえば Python とかは
KeyError
を返してきます
- たとえば Python とかは
- 条件文に
bool
ではない値が入っている- ただし、
undefined
は JavaScript の暗黙の型変換によって false として扱われる - falsy ではない値は true として扱われる(Truthy)
- ただし、
- 三項演算子か代入のどちらかが、次の行を読むまでわからない
ちょっと書き換えてみる:暗黙の型変換を避ける
const inventory = [
{ name: "asparagus", type: "vegetables", quantity: 5 },
{ name: "bananas", type: "fruit", quantity: 0 },
{ name: "goat", type: "meat", quantity: 23 },
{ name: "cherries", type: "fruit", quantity: 5 },
{ name: "fish", type: "meat", quantity: 22 },
];
const key = "type"
let ret = {};
for (const item of inventory) {
const index = item[key];
if (index in ret) {
ret[index].push(item);
} else {
ret[index] = [item];
}
}
// 以下テストコード
const res = inventory.reduce((accumulator, current) => {
const index = current[key];
accumulator[index] = accumulator[index]
? [...accumulator[index], current]
: [current];
return accumulator;
}, {});
console.log(ret)
const result = JSON.stringify(res) === JSON.stringify(ret)
console.log("JSON.stringify(res) === JSON.stringify(ret):",result)
-
in
演算子を使えばbool
にでき、暗黙の型変換を避けつつ代入と見間違うことはない - reduce と分割代入はお好みで使ったり使わなかったりしてください
JavaScript のふしぎな動作
なんで暗黙の型変換を避けたいかと言えば、こういうことがあるからです。
[] ? "T" : "F";
// "T"
[] == true ? "T" : "F";
// "F"
なんでこうなるの?
比較演算子 ==
は、比較する値の型が異なる場合、JavaScript内部で暗黙の型変換を行うからです。
[] == "" ? "T" : "F"
// "T"
[] == 0 ? "T" : "F"
// "T"
"" == false ? "T" : "F"
// "T"
[] == false ? "T" : "F"
// "T"