JavaScript には isNumber
というメソッドなく、整数かどうか判定する Number.isInteger()
と有限数かどうか判定する Number.isFinite()
, isFinite()
だけなので、数値かどうか判定したい時は独自実装するかライブラリをつかうしか無いのですが暗黙の型変換があるので意外とハマりどころがあります。( TypeScript 使え!ってのは無しで、
結論から書けば、typeof
が number
なもので、NaN
と Infinity
を除外すれば有限数な数値かどうか判定できる。
const isNumber = (n) => {
return typeof(n) === 'number' && n - n === 0;
};
of
Number.isFinite(n);
暗黙の型変換のヤバイやつ
JavaScript で簡易的に数値に変換する方法として - 0
する方法があります。
"10" - 0;
"a" - 0;
これを利用した数値かどうか判定するような関数
const isNumber = (n) => {
const v = n - 0;
if ( v || v === 0 ) {
return true;
}
return false;
};
渡される値がある程度決まっている場合は問題ないのですが、特定の値の時意図しない動作になってしまう事があります
✅isNumber( 1 );
✅isNumber( -1 );
✅isNumber( 10.1 );
✅isNumber( -1.1 );
✅isNumber( 5e3 );
✅isNumber( 10e+3 );
✅isNumber( 10e-3 );
✅isNumber( 0xff );
✅isNumber( Math.PI );
✅isNumber( parseInt('012') );
✅isNumber( parseInt('012.5') );
✅isNumber( Infinity );
✅isNumber( -Infinity );
✅isNumber( '10' );
✅isNumber( '-10' );
✅isNumber( NaN );
⛔️isNumber( null );
✅isNumber( undefined );
⛔️isNumber( true );
⛔️isNumber( false );
⛔️isNumber( '' );
⛔️isNumber( ' ' );
✅isNumber( 'string' );
⛔️isNumber( [] );
⛔️isNumber( [1] );
✅isNumber( {} );
✅isNumber( {a: 1} );
✅isNumber( function() {} );
これは - 0
で数値化する際に暗黙の型変換で数値に変換されてしまう値があるためです
null - 0;
true - 0;
false - 0;
"" - 0;
" " - 0;
[] - 0;
[1] - 0;
数値かどうか判定する
数値でかつ NaN
, Infinity
は除外したい
コード
const isNumber = (n) => {
if ( typeof(n) === 'number' && Number.isFinite(n) ) {
return true;
}
return false;
};
or
const isNumber = (n) => {
if ( typeof(n) === 'number' && n - n === 0 ) {
return true;
}
return false;
};
👇 test
✅ isNumber( 0 );
✅ isNumber( 1 );
✅ isNumber( -1 );
✅ isNumber( 10.1 );
✅ isNumber( -1.1 );
✅ isNumber( 5e3 );
✅ isNumber( 10e+3 );
✅ isNumber( 10e-3 );
✅ isNumber( 0xff );
✅ isNumber( Math.PI );
✅ isNumber( parseInt('012') );
✅ isNumber( parseFloat('012.5') );
✅ isNumber( Infinity );
✅ isNumber( -Infinity );
✅ isNumber( NaN );
✅ isNumber( null );
✅ isNumber( undefined );
✅ isNumber( true );
✅ isNumber( false );
✅ isNumber( "10" );
✅ isNumber( "-10" );
✅ isNumber( "" );
✅ isNumber( " " );
✅ isNumber( "string" );
✅ isNumber( [] );
✅ isNumber( [ 1 ] );
✅ isNumber( {} );
✅ isNumber( { a: 1 } );
✅ isNumber( function() {} );
文字列の数字も true にする
先の数値判定に文字列で数字になるものを true にする判定を追加すればOK
const isNumberAllowString = (n) => {
const type = typeof(n);
if ( type === 'number' && Number.isFinite(n) ) {
return true;
}
if ( type === 'string' && n.trim() !== '' && Number.isFinite(n - 0) ) {
return true;
}
return false;
};
👇 test
✅ isNumberAllowString( 0 );
✅ isNumberAllowString( 1 );
✅ isNumberAllowString( -1 );
✅ isNumberAllowString( 10.1 );
✅ isNumberAllowString( -1.1 );
✅ isNumberAllowString( 5e3 );
✅ isNumberAllowString( 10e+3 );
✅ isNumberAllowString( 10e-3 );
✅ isNumberAllowString( 0xff );
✅ isNumberAllowString( Math.PI );
✅ isNumberAllowString( parseInt('012') );
✅ isNumberAllowString( parseFloat('012.5') );
✅ isNumberAllowString( "10" );
✅ isNumberAllowString( "-10" );
✅ isNumberAllowString( Infinity );
✅ isNumberAllowString( -Infinity );
✅ isNumberAllowString( NaN );
✅ isNumberAllowString( null );
✅ isNumberAllowString( undefined );
✅ isNumberAllowString( true );
✅ isNumberAllowString( false );
✅ isNumberAllowString( "" );
✅ isNumberAllowString( " " );
✅ isNumberAllowString( "string" );
✅ isNumberAllowString( [] );
✅ isNumberAllowString( [ 1 ] );
✅ isNumberAllowString( {} );
✅ isNumberAllowString( { a: 1 } );
✅ isNumberAllowString( function() {} );
解説的なもの
typeof で判定
typeof()
が number
がになるもので判定すると先の暗黙の変換で数値になるものを除外することができる
typeof( null );
typeof( true );
typeof( false );
typeof( "" );
typeof( " " );
typeof( [] );
typeof( [1] );
NaN
, Infinity
を除外する
NaN
, Infinity
は number
なので別の条件で除外する
isFinite
isFinite
渡された値が有限数かどうかを判定します。
cf. isFinite() - JavaScript | MDN
JavaScript には isFinite
と Number.isFinite
がある。
e.g.
Number.isFinite( Infinity );
Number.isFinite( -Infinity );
Number.isFinite( NaN );
同値の引き算を利用する
同値で引き算をすると有効数だと 0 になるが、Infinity
, NaN
は NaN
になることを利用して除外する
Infinity - Infinity;
-Infinity - (-Infinity);
NaN - NaN ;
文字列の数字を判定
string - 0
で数値化して、 isFinite()
で NaN
と Infinity
になるものを弾く
"a" - 0;
"Infinity" - 0;
"-Infinity" - 0;
ただし空文字列だけは 0
になってしまうので別途除外する必要がある
"" - 0;
" " - 0;
"".trim();
" ".trim();
所感
文字列の数字も許可したい場合は、is-number というライブラリを使うのが楽だと思います。
[参考]