【JS】分割代入の初期値はFalsyでもNullishでもなくundefinedの時だけ働く
概要
タイトルが全てを物語っていますが、自分の中で思い違いをしていた(+知らないといつかやらかしそう)ので紹介します。
React
の記事でよく使われる、JS
の分割代入の話です。
経緯
とあるアプリケーションのバックエンドをNode
で実装していて、対象データのUPDATE
処理を書いていた時でした。
引数はREST API
のPOST
で受け取ったリクエストボディがそのまま入ってくるイメージだったので、ざっくりとコードは以下のような感じです。
キーにするid
と必須項目であるpropA
は入力チェックをして、任意のpropB
は値があれば更新し、なければしないというものです。
propB
については フロント側から空文字で送られてきた場合も更新したくない ため、分割代入した時にデフォルト値をnull
にすることで対応する意図でした。
const updateHoge = (body) => {
const { id, propA, propB = null} = body;
if(id && propA) {
let sql = [` UPDATE HOGE SET`];
sql.push(` PROP_A = ${propA} `);
if(propB !== null) {
sql.push(` PROP_B = ${propB} `);
}
sql.push(` WHERE id = ${id} `);
}
else {
// id,propAが不正な場合のエラー処理
}
}
実際sql
周りの処理はもうちょっと綺麗に書いていましたが、だいたいは上記のようなイメージです。
察しのいい方ならもうお分かりかと思いますが、この書き方だと propB
が空文字でも空文字で更新してしまいます。
undefined
の時のみはたらく
分割代入の初期値(規定値)はReact
のコンポーネントでProps
を変数に格納する時などに以下の書き方をされている方も多いかと思います。
const {hoge, fuga = 10} = props;
この時にfuga=10
と記載しているのが分割代入の初期値(規定値)で、自分はこれがFalsy
の時に動作するものだとばかり思っていました。
Falsy
とは文字通りfalse
として判定される値のことで空文字の""
やNaN
などがそれにあたります。
過去にも自分が以下のような記事でまとめているので、興味がある方はそちらを参照ください。
Falsy
の他にNullish
という値もあり、これはnull
もしくはundefined
を指します。
Null合体演算子などを使われている方にはおなじみの言葉だと思います。
// fugaがNullishの場合のみ??の後の文字列が入る
const hoge = fuga ?? "fuga is Nullish";
さて話を分割代入に戻しますが、 分割代入の初期値が使われるのは対象のプロパティがFalsy
の時やNullish
の時ではなくundefined
の時 です。
オブジェクトから取り出した値が undefined であるときの既定値を、変数に割り当てることができます。
冒頭のコードは以下のようになっていました。
const { id, propA, propB = null} = body;
これはpropB
がundefined
の時のみnull
が入り、それ以外のケースではpropB
の値を使います。
従ってpropB
が空文字""
の場合はnull
に置き換わらずにそのまま動作します。
この場合どうすればよかったかというと、後述のSQLの処理中でpropB
が空文字かどうかを判定してあげればいいと思います。
※もしくはFalsy
かどうかで判定するのもよいかと思います。
一応試してみる
簡単に試せそうなので、検証してみました。
const test = {
a: null,
b: "",
c: 0,
d: 1,
e: undefined,
f: {},
g: [],
h: NaN,
i: false,
j: true,
}
const {
a = "CHANGED",
b = "CHANGED",
c = "CHANGED",
d = "CHANGED",
e = "CHANGED",
f = "CHANGED",
g = "CHANGED",
h = "CHANGED",
i = "CHANGED",
j = "CHANGED",
k = "CHANGED"
} = test;
console.log(" a --> " + a);
console.log(" b --> " + b);
console.log(" c --> " + c);
console.log(" d --> " + d);
console.log(" e --> " + e);
console.log(" f --> " + f);
console.log(" g --> " + g);
console.log(" h --> " + h);
console.log(" i --> " + i);
console.log(" j --> " + j);
console.log(" k --> " + k);
これを実行すると以下のようになります。
a --> null
b -->
c --> 0
d --> 1
e --> CHANGED
f --> [object Object]
g -->
h --> NaN
i --> false
j --> true
k --> CHANGED
確かに明示的にundefined
にしたe
と、そもそも定義しなかった(暗黙的にundefined
にした)k
だけが"CHANGED"
の値に置き換わっています。
まとめ
今回はJavascript
の分割代入において、初期値が入る条件について自分が思い違いをしていたので紹介しました。
Falsy
やNullish
といった値の判定をミスると、回り回って大きな障害につながる可能性もあるので、忘れずに抑えていきたいところです。
今回の内容が役立てば幸いです。
Discussion