【STEP.08】
JavaScriptの型変換・型判定の方法をマスターしよう!

型変換が必要な理由

JavaScriptはデータ型に寛容な言語で、その時々の文脈(前後の関数や演算子)によって、操作対象の値を適切なデータ型に自動的に変換してくれます。

しかし、この自動変換が時として、思わぬバグの温床になるようなケースもあります。

そこで、JavaScriptではデータ型を明示的に変換するための方法を提供しています。

データ型を明確にしたうえで処理を行いたい場合、あるいは、変数の内容がそもそもあいまいである場合には、明示的にデータ型を変換することで、スクリプトの思わぬ挙動を未然に防ぐことができます。

文字列を数値に変換する【Number.parseInt/parseFloatメソッド、Number関数】

Number.parseIntparseFloatメソッド、Number関数もデータ型を明示的に変換する方法のひとつです。

Number.parseIntparseFloatメソッド、Number関数は、いずれも「与えられた値を数値に変換する」という点で共通しています。

しかし、細かな挙動は微妙に異なるので、要注意です。

具体的なサンプルを確認してみましょう。

文字列の混在した数値を変換する例

まずは、文字列の混在した数値の変換例です。

// 文字列の混在した数値
let data1 = '888abc';
console.log(Number.parseInt(data1));
// 結果:888
console.log(Number.parseFloat(data1));
// 結果:888
console.log(Number(data1));
// 結果:NaN

まず、parseXxxxxメソッドは「888abc」のような文字列混在の数値も、数字として解析できる部分を先頭から取り出して変換しようとしますが、Number関数は解析できずにNaNを返します。

16進数と指数表現を変換する例

次は、16進数と指数表現の変換例です。

// 16進数
let data2 = '0x10';
console.log(Number.parseInt(data2));
// 結果:16
console.log(Number.parseFloat(data2));
// 結果:0
console.log(Number(data2));
// 結果:16

// 指数表現
let data3 = '1.414E3';
console.log(Number.parseInt(data3));
// 結果:1
console.log(Number.parseFloat(data3));
// 結果:1414
console.log(Number(data3));
// 結果:1414

parseFloatメソッドは16進数表現を認識できずに、 数字として解析できる部分を先頭から取り出した結果、0を返します。

逆に、parseIntメソッドは指数表現を認識できず、 数字として解析できる部分を先頭から取り出し、整数に変換した結果を返しています。

2、8進数表現を変換する例

なお、ES2015で導入された2、8進数表現は、次のようにNumber関数以外では正しく解析できません。

// 2進数
let data4 = '0b100';
console.log(Number.parseInt(data4));
// 結果:0
console.log(Number.parseFloat(data4));
// 結果:0
console.log(Number(data4));
// 結果:4

// 8進数
let data4 = '0o10';
console.log(Number.parseInt(data4));
// 結果:0
console.log(Number.parseFloat(data4));
// 結果:0
console.log(Number(data4));
// 結果:8

parseIntメソッドでも解析できずに「0b~0o~」の前の0を返すだけです。

オブジェクトを変換する例

次は、オブジェクトを渡した例です。

// オブジェクト
let data5 = new Date();
console.log(Number.parseInt(data5));
// 結果:NaN
console.log(Number.parseFloat(data5));
// 結果:NaN
console.log(Number(data5));
// 結果:1572783873912

parseXxxxxメソッドは解析を諦めて単純に非数値を返します。

しかし、Number関数だけはオブジェクトを数値表現したものを返します。(この例であれば、現在時刻のタイムスタンプ値を返します。)

parseInt/parseFloat関数について

Number.parseIntparseFloatメソッドは、ES2015で導入されたメソッドです。

ES2015より前では同名のグローバル関数parseIntparseFloatを利用します。

いずれも挙動は同じですが、数値関連の機能はNumberオブジェクトにまとまっていたほうがわかりやすいことから、そのように改められました。

値を文字列型/論理型に変換する【String関数/Boolean関数】

値を文字列型/論理型に変換するには、それぞれStringBoolean関数を利用します。

console.log(typeof String(123));
// 結果:string
console.log(typeof Boolean(-1));
// 結果:boolean

Boolean関数は、空文字列、ゼロ、NaN、null、undefinedをfalse、それ以外をtrueと見なします。

console.log(Boolean(""));
// 結果:false
console.log(Boolean(0));
// 結果:false
console.log(Boolean(NaN));
// 結果:false
console.log(Boolean(null));
// 結果:false
console.log(Boolean(undefined));
// 結果:false

たとえば、「'false'」のような文字列も、Boolean関数の戻り値はtrueなので注意してください。(空でない文字列はすべてtrueです。)

console.log(Boolean('false'));
// 結果:true

簡単に型変換を行う方法

数値⇔文字列の変換は、算術演算子「+」「-」を利用することによっても実現可能です。

「+」演算子を使って数値を文字列へ変換する

数値を文字列に変換するには+演算子を利用します。

console.log(typeof(123 + ''));
// 結果:string

+演算子は特殊な演算子で、オペランドに文字列が含まれている場合に(加算ではなく)文字列連結として機能します。

ここではその性質を利用して、空文字列を加えることで、数値を文字列に変換しています。

「-」演算子を使って文字列を数値へ変換する

文字列から数値への変換には演算子を利用します。

console.log(typeof('123' - 0));
// 結果:number

ここでは、演算子がオペランドを必ず数値として処理することを利用して、文字列「'123'」を強制的に数値に変換しています。

ちなみに、「'123' + 0」は不可です。

先ほど述べたように、+演算子はオペランドの片方が文字列の場合、文字列連結として機能するからです。

console.log(typeof('123' + 0));
// 結果:string

「!」演算子を使って論理型へ変換する

!演算子(否定)を利用することで、任意の値を強制的に論理型に変換できます。

let num = 123;
console.log(!!num);
// 結果:true

!演算子がオペランドとして論理型を要求することを利用して、「!!」で二重に値を反転させています。

型判定【Number.isInteger/Number.isNaN/Number.isFinite/Array.isArray】

JavaScriptはデータ型を判定するために、次に掲げる表のようなメソッドを用意しています。

【データ型を判定するためのメソッド】
メソッド概要
Number.isInteger整数であるかNumber.isInteger(1)
// 結果:true
Number.isNaNNaN(Not a number)であるかNumber.isNaN(undefined)
// 結果:false
Number.isFinite有限値であるかNumber.isFinite(0)
// 結果:true
Array.isArray配列であるかArray.isArray([])
// 結果:true

ES2015より前では、グローバル関数として同名のisNaNisFiniteも存在しましたが、Number.isNaNisFiniteメソッドと挙動が異なるので注意が必要です。

console.log(Number.isNaN('xyz'));
// 結果:false
console.log(isNaN('xyz'));
// 結果:true

isNaN関数が引数を数値に変換してから判定するのに対して、Number.isNaNメソッドは引数が数値型で、かつ、NaNである場合にだけtrueを返します。

つまり、Number.isNaNメソッドのほうがより確実にNaN値を判定できるということです。

この関係は、isFiniteメソッドも同様です。

MEMO
NaNとは
NaN(Not a Number)は、たとえば「ゼロをゼロで除算した」など、不正な演算が行われた場合に、数値として表現できない結果を表すために利用します。

NaNは一種独特な値で、自分自身を含むすべての値と等しくない、という性質を持ちます。

つまり、「NaN === NaN」はfalseです。

NaN値を判定するには、Number.isNaNメソッドを利用しなければなりません。

型判定【typeof演算子】

typeof演算子は、オペランドに指定した変数/リテラルのデータ型を表す文字列を返します。

具体的な例を見てみましょう。

let str = 'はじめまして';
console.log(typeof str);
// 結果:string

let num = 100;
console.log(typeof num);
// 結果:number

let flag = false;
console.log(typeof flag);
// 結果:boolean

let ary = ['Vue.js','TypeScript','ECMAScript'];
console.log(typeof ary);
// 結果:object
	
let date = new Date();
console.log(typeof date);
// 結果:object

let ex = /^[A-Za-z]{1,}/;
console.log(typeof ex);
// 結果:object

console.log(typeof null);
// 結果:object

ただし、typeof演算子で識別できるのは文字列/数値/真偽型のような基本データ型に限定されます。

配列や日付、正規表現、nullなどは一様に「object」と見なされる点に注意してください。

また、文字列/数値/真偽型についてラッパーオブジェクトとして宣言した場合には、同じく「object」と見なされます。

let flag2 = new Boolean(false);
console.log(typeof flag2);
// 結果:object

オブジェクトの種類を判別したい場合には、instanceof演算子、constructorプロパティなどを利用します。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です