順番に読み進めながら学べます

型変換 — Number / String / parseInt と暗黙変換

入力欄から届いた文字列を数値に変える明示的な変換と、演算子が自動で型をそろえる暗黙の変換を扱います。typeof での型の確認、変換に失敗したときの NaN の見分け方まで押さえます。

入力欄に打ち込まれた数量や、外部から受け取ったデータの中の金額。こうした値は、画面に出ている見た目が同じ 1200 でも、JavaScript が文字列として持っているか数値として持っているかで計算の結果が変わります。

この記事では、値の型を自分で変える 明示的な型変換Number などを呼んで型を変える書き方)と、演算子が自動で型をそろえる 暗黙の型変換(演算子が計算の前に型を合わせる動き)の 2 つを扱います。

今の型を確かめる — typeof

型をそろえる作業は、いま何型なのかが分かっていないと始まりません。合計金額がおかしい、比較が思った結果にならないといった不具合は、値が数値だと思い込んでいたところが実は文字列だった、という取り違えから起こります。

まず、値の型をその場で確認する方法を押さえます。

typeof(値の型名を文字列で返す演算子)を値の前に置くと、その値の型が分かります。typeof 1200"number"typeof "1200""string" です。

返ってくるのは型そのものではなく 型名を表す文字列 なので、判定に使うときは typeof price === "number" のようにクォートで囲んだ文字列と比べます。

typeof が返すもの
typeof "A-1042"型そのものではなく型名の文字列が返る"string"typeof 1200判定は === "number"と比べる"number"typeof trueクォートを外したstring とは比べない"boolean"
返るのは型そのものではなく、型名を表す文字列 です。判定するときはクォートで囲んだ文字列と比べます。
const orderId = "A-1042";   // 注文番号

console.log(typeof orderId);   // string
console.log(typeof 500);       // number
console.log(typeof true);      // boolean

// 変数だけでなく、式の結果にも使える
console.log(typeof (500 + 100));            // number
console.log(typeof (500 > 100));            // boolean
console.log(typeof `注文番号 ${orderId}`);    // string

商品の編集画面から受け取った 3 つの値が、それぞれ何型で届いているのかを確かめます。inputPrice / stockCount / isPublished は宣言済みです。

① inputPrice の型を表示してください。

② stockCount の型を表示してください。

③ isPublished の型を表示してください。

④ inputPrice が数値型ではないことを判定して、その結果を表示してください。

(正しく実行できれば解説が表示されます)

JavaScript / TypeScript エディタ

コードを実行してください

暗黙の変換 — 足し算だけが文字列連結になる

型が違う値どうしを計算しても、JavaScript はエラーで止まりません。演算子が計算の前に型をそろえて、そのまま先へ進みます。

== が比較の前に型をそろえていたのと同じ動きが、算術演算子でも起きます。止まらないぶん、結果を見るまで取り違えに気付けません。

問題は、+ だけが他の演算子と違う判断をすることです。+ は、片方が文字列なら文字列連結を選びます。数値の側が文字列に変換され、"3" + 1"31" になります。

一方 - * / % には文字列どうしをつなぐ意味がないので、文字列のほうを数値に変換してから計算します

合計欄に金額が横に並んで表示されるときは、足す前に変換されていないと考えられます。

演算子ごとに寄せる型が違う
"3" + 1文字列に寄せてつなぐ"31""3" - 1数値に寄せて計算する2"3" * 2数値に寄せて計算する6
+ だけが 文字列連結 を優先します。ほかの算術演算子は文字列のほうを数値に変換します。
const inputQuantity = "3";   // 数量の入力欄から受け取った値 (文字列)

// 表示だけでは数値の 31 と文字列の "31" を見分けられないので、下の typeof で確かめる
console.log(inputQuantity + 1);   // 31   文字列 "31" として連結される
console.log(inputQuantity - 1);   // 2    数値に変換してから引く
console.log(inputQuantity * 2);   // 6    掛け算も数値に変換される
console.log(inputQuantity / 3);   // 1    割り算も数値に変換される

// + の結果だけ型が違うことを typeof で確かめられる
console.log(typeof (inputQuantity + 1));   // string
console.log(typeof (inputQuantity - 1));   // number

外から届いた値は文字列だと考える

入力欄や、外部から受け取ったデータの中の数字は、文字列として届くのが普通 です。1200 + 300 のつもりで書いた足し算が "1200300" のように横に並ぶときは、片方が文字列のままだったサインです。足す前に数値へ変換します。

明示的に型を変える — Number / String / Boolean

演算子任せの変換は、どちらの型に寄るかが演算子ごとに決まっているため、書いた本人の意図が残りません。計算に使う値は、計算する前に自分で型をそろえて おくと、結果を追いやすくなります。

JavaScript には型ごとに変換用の関数が用意されています。

Number(値) は数値へ、String(値) は文字列へ、Boolean(値) は真偽値へ変換した 新しい値を返します。元の変数は書き換わりません。

Boolean が返す結果は falsy の規則そのままで、""0false、中身のある文字列は true です。なお Number("")NaN ではなく 0 を返すので、未入力の欄をそのまま数値にすると 0 円として扱われます。

3 つの変換関数が返す値
Number("1200")文字列 → 数値1200String(1200)数値 → 文字列"1200"Boolean("")文字列 → 真偽値false
どれも 新しい値を返す 関数で、渡した変数のほうは変わりません。
const inputQuantity = "3";   // 数量の入力欄から受け取った値
const shippingFee = 500;     // 送料 (数値)

console.log(Number(inputQuantity));         // 3     文字列から数値へ
console.log(Number(inputQuantity) + 1);     // 4     足し算も数値として動く
console.log(String(shippingFee));           // 500   数値から文字列へ
console.log(typeof String(shippingFee));    // string

console.log(Boolean("東京都"));   // true    中身のある文字列
console.log(Boolean(""));         // false   空文字列は falsy
console.log(Number(""));          // 0       空文字列は 0 になる

// 変換しても元の変数は文字列のまま
console.log(typeof inputQuantity);   // string

カートの小計を、入力欄から届いた数量と単価から求めます。inputQuantity / unitPrice / inputCoupon は宣言済みです。

① inputQuantity を数値に変換した結果を表示してください。

② ① で得た数値と unitPrice から小計を求めて表示してください。

③ ② の小計を文字列に変換したときの型を表示してください。

④ 未入力のクーポン欄 inputCoupon を真偽値に変換した結果を表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

変換に失敗した値 — NaN と Number.isNaN

数値にできない文字列を Number に渡しても、JavaScript はエラーを出しません。代わりに NaN(数値として表せなかったことを表す値)を返し、そのまま次の計算へ進みます。

金額欄に全角文字やカンマが混ざっていただけで、合計が最後まで NaN のまま画面に出てしまうのはこのためです。変換したあとに、成功したかどうかを自分で確かめる必要があります。

ここで total === NaN と書いても判定できません。NaN は自分自身と比べても一致しない ためで、結果は必ず false です。

typeof NaN"number" を返すので型でも見分けられません。判定には Number.isNaN(渡された値が NaN かどうかを返す関数)を使います。

const inputAmount = "1,200";   // カンマ付きで打ち込まれた金額

console.log(Number(inputAmount));         // NaN   カンマがあると変換できない
console.log(Number(inputAmount) + 500);   // NaN   混ざったあとの計算も NaN

// 比較でも型でも見分けられない
console.log(Number(inputAmount) === NaN);   // false
console.log(typeof NaN);                    // number

// 判定は専用の関数を使う
console.log(Number.isNaN(Number(inputAmount)));   // true

金額欄に入力された値が数値として扱えるかどうかを確かめ、扱えないときだけ案内を出します。inputAmount / validAmount は宣言済みです。

① inputAmount を数値に変換した結果を表示してください。

② ① の結果が変換に失敗した値かどうかを判定して表示してください。

③ validAmount についても同じ判定を行い、結果を表示してください。

④ inputAmount の変換に失敗しているときだけ「金額を数字で入力してください」と表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

数字で始まる文字列を読む — parseInt と parseFloat

"240px""12.5%" のように、数字のうしろに単位が付いた文字列を扱う場面があります。Number文字列全体 を数値として読むため、単位が残っていると NaN になります。

先頭の数字だけを取り出したいときは別の関数を使います。

parseInt(先頭から整数として読める範囲を取り出す関数)は "240px" から 240 を取り出します。2 つ目の引数に渡す 10 は「ふだん使う 0〜9 の数え方で読む」という指定です。省略もできますが、書いておくと読む側に意図が伝わります。

小数点まで含めて読みたいときは parseFloat(先頭から小数として読める範囲を取り出す関数)を使います。どちらも先頭から数字として読める部分が無ければ NaN を返します。

Number と parseInt / parseFloat の読み方の違い
Number("240px")全体を数値として読もうとするNaNparseInt("240px")先頭から整数として読める分だけ240parseFloat("12.5%")先頭から小数として読める分だけ12.5
Number文字列全体 を見ます。parseIntparseFloat先頭から読める範囲 だけを取り出し、小数点まで読むかどうかが違います。
const cardWidth = "240px";   // スタイル指定から読み取った幅

console.log(Number(cardWidth));         // NaN    全体を数値にできない
console.log(parseInt(cardWidth, 10));   // 240    先頭から読める分だけ

console.log(parseFloat("12.5%"));       // 12.5   小数点まで読み取る
console.log(parseInt("12.5%", 10));     // 12     整数として読むので小数は落ちる

// 先頭が数字でなければ読み取れない
console.log(parseInt("約 240px", 10));   // NaN

先頭だけ読むので気付きにくい取りこぼしが出る

parseInt読めなくなった時点で止まります。カンマ区切りの "1,200"1 になり、"12.5"12 になります。どちらもエラーにならないので、金額のように全体を読み切りたい値には Number を使い、単位付きの文字列にだけ parseInt を使います。

スタイル指定と表示用のテキストから、数値部分だけを取り出します。cardWidth / discountText は宣言済みです。

① cardWidth を文字列全体として数値に変換した結果を表示してください。

② cardWidth から数値部分を整数として取り出して表示してください。

③ discountText から数値部分を小数のまま取り出して表示してください。

④ ② で取り出した値を 2 倍にした結果を表示してください。

JavaScript / TypeScript エディタ

コードを実行してください
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1console.log("5" + 1); を実行すると何が表示されますか?

Q2console.log(Number("240px")); の結果はどれですか?

Q3変換した結果が NaN かどうかを正しく判定できる書き方はどれですか?