0
0

groupBy で学ぶ JavaScript の真偽値

Posted at

なにこの記事&なぜ

  • ES6 以降の構文で groupBy を書いた。そのときに調べたことを残す。
  • Object.groupBy() - JavaScript | MDN
    • ここのサンプルコードをブラウザのコンソールにコピペしたら動かなかった(記事を書いてるときにコピペしたら動きました)のがきっかけ。

先に結論だけ教えて

  • JavaScript ではデータを持たないことを示す型が nullundefined に分かれている
  • JavaScript では連想配列に存在しないキーを指定してもエラーにならず、undefined を返す
  • undefinedfalse として扱われる値のひとつ(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 を返してきます
  • 条件文に 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"

参照

0
0
2

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