一覧PG-02-2 · 型と変換

JavaScriptの暗黙の型変換

文字列の入力を加算・減算・比較へ渡し、値と型を一緒に確認します。最後に空入力と変換できない文字を検査し、数値として使う条件を明示します。

説明

JavaScriptでは演算子によって数値や文字列への変換が行われます。同じ入力でも+と-で違う結果になり、空文字列を数値へ変換すると0になる場合もあります。

文字列の入力を加算・減算・比較へ渡し、値と型を一緒に確認します。最後に空入力と変換できない文字を検査し、数値として使う条件を明示します。

1入力値と型

入力欄から得た値を想定して、文字列"5"をrawに置きます。typeofで型を調べます。

let raw = "5"文字列の入力値; [raw, typeof raw]値と型

見える文字は5でも型はstringです。ここから先の式は、同じrawを使い続けます。角括弧で結果を配列へまとめています。

2加算と減算

rawへ2を足す式と、2を引く式を並べます。

[raw + 2, typeof (raw + 2)連結とその型, raw - 2, typeof (raw - 2)数値変換後の減算と型]

+は一方が文字列になると連結し、結果はstringの52です。-は数値へ変換して計算するためnumberの3になります。表示だけではなく型も確認すると、計算経路の違いが分かります。

3括弧でまとまりを変える

数字の加算を先に終える場合と、先に文字列へ連結する場合を比べます。

[raw + 2 + 1左から連結, raw + (2 + 1)括弧内の加算を先に実行, Number(raw) + 2 + 1明示的な数値変換]

左から連結すると521、括弧内を先に加算すると53です。Number(raw)を先に使えば数量として8になります。括弧は型変換を直接指示するものではなく、どの式の結果が次の演算へ渡るかを変えます。

4値だけでなく型も一致する比較

文字列5と数値5を、==と===で比較します。空文字列と0も並べます。

[raw == 5, raw === 5変換する比較と厳密な比較, "" == 0, "" === 0空文字列と数値0]

==では変換によってtrueになる組合せがあります。===ではstringとnumberは一致しません。入力を数値へ変換する処理と、その後の比較を分けると、意図しない同一扱いを減らせます。

5数値へ変換した結果

空文字、空白、null、undefined、数値でない文字をNumberへ渡します。

[Number(""), Number(" "), Number(null)0になる入力, Number(undefined), Number("five")NaNになる入力]

空文字・空白・nullは0になり、undefinedとfiveはNaNになります。NaNもtypeofではnumberなので、型がnumberという条件だけでは有効な数量を保証できません。

6NaNと文字列の真偽

NaNをNaNと比較する方法、専用の検査、文字列falseの真偽を比べます。

[NaN === NaNNaN同士の比較, Number.isNaN(Number("five"))NaNの検査, typeof NaNNaNの型, Boolean("false"), Boolean("")空でない文字列と空文字列]

NaN同士の===はfalseです。NaNの検査にはNumber.isNaNを使えます。文字列falseは空でないのでtrueで、単にBooleanへ渡しても設定文字列のfalseを解釈する処理にはなりません。

7空入力と数値の条件を明示する

今回は空でない文字列で、変換後が有限の数値であることを受入れ条件にします。Number.isFiniteはNaNやInfinityを除外します。

const parseAmount = text =>入力を検査する関数 text.trim() !== ""空白だけの入力を除く && Number.isFinite(Number(text))有限の数値になるか確認 ? Number(text) : null成功値か不在値を返す; ["5", "", " ", "five", "0", "Infinity"].map(parseAmount)同じ条件を各入力へ適用

5と0は数値として残り、空文字、空白、five、Infinityはnullになります。受入れる表記は用途で追加制限できます。例えば整数のみ、負数禁止、16進表記禁止などは、この条件だけでは保証されません。

8検査済みの値を計算へ渡す

変換できた5を2倍し、0も欠落させず扱います。

const amount = parseAmount(raw)検査済みの入力値; [amount * 2数値の乗算, parseAmount("0") ?? 990を保持, parseAmount("") ?? 99不在時だけ代替値]

結果は10、0、99です。??はnullまたはundefinedの場合だけ代替値を使うため、正当な0を保持できます。入力の解析、検査、計算を順に行うと、暗黙変換に任せる箇所を減らせます。

まとめ

演算子や括弧によって、連結・数値変換の順番が変わります。

入力の空欄、NaN、正当な0を用途に合う条件で扱います。

操作履歴と解説を振り返れます。

Node.js

1
let raw = "5"; [raw, typeof raw]
[ '5', 'string' ]
2
[raw + 2, typeof (raw + 2), raw - 2, typeof (raw - 2)]
[ '52', 'string', 3, 'number' ]
3
[raw + 2 + 1, raw + (2 + 1), Number(raw) + 2 + 1]
[ '521', '53', 8 ]
4
[raw == 5, raw === 5, "" == 0, "" === 0]
[ true, false, true, false ]
5
[Number(""), Number(" "), Number(null), Number(undefined), Number("five")]
[ 0, 0, 0, NaN, NaN ]
6
[NaN === NaN, Number.isNaN(Number("five")), typeof NaN, Boolean("false"), Boolean("")]
[ false, true, 'number', true, false ]
7
const parseAmount = text => text.trim() !== "" && Number.isFinite(Number(text)) ? Number(text) : null; ["5", "", " ", "five", "0", "Infinity"].map(parseAmount)
[ 5, null, null, null, 0, null ]
8
const amount = parseAmount(raw); [amount * 2, parseAmount("0") ?? 99, parseAmount("") ?? 99]
[ 10, 0, 99 ]

演習完了