数値を扱う時や数値変換を行う時に0
が鬼門になることが多いのでメモ
var checklist = [ 0, "0", "", undefined, "undefined", false, "false", true, "true", null, "null", NaN, "NaN", Infinity, "Infinity", -Infinity, "-Infinity" ];
-0で数値変換した場合
checklist.forEach(function(v) { console.log(v + " (" + typeof(v) + ") =>", v-0); });
出力👇
0 (number) => 0 "0" (string) => 0 "" (string) => 0 undefined (undefined) => NaN "undefined" (string) => NaN false (boolean) => 0 "false" (string) => NaN true (boolean) => 1 "true" (string) => NaN null (object) => 0 "null" (string) => NaN NaN (number) => NaN "NaN" (string) => NaN Infinity (number) => Infinity "Infinity" (string) => Infinity -Infinity (number) => -Infinity "-Infinity" (string) => -Infinity
isNaN() と Number.isNaN()
isNaN()
と Number.isNaN()
とでは判定結果が異なる。
isNaN()
は暗黙の型変換でNaN
になるものも含まれるっぽい。
isNaN()
checklist.forEach(function(v) { if( isNaN(v) ) { console.log('isNaN >', v, "("+typeof(v)+")"); } });
出力👇
isNaN > undefined (undefined) isNaN > "undefined" (string) isNaN > "false" (string) isNaN > "true" (string) isNaN > "null" (string) isNaN > NaN (number) isNaN > "NaN" (string)
Number.isNaN() (ES6)
checklist.forEach(function(v) { if( Number.isNaN(v) ) { console.log('Number.isNaN >', v, "("+typeof(v)+")"); } });
出力👇
Number.isNaN > NaN (number)
isFinite() と Number.isFinite()
isNaNと同様で判定結果が異なる。
isNaNと同じくglobalにある isFinite()
は暗黙の型変換で判定してるっぽい。
isFinite()
checklist.forEach(function(v) { if( isFinite(v) ) { console.log('isFinite >', v, "("+typeof(v)+")"); } });
出力👇
isFinite > 0 (number) isFinite > "0" (string) isFinite > "" (string) isFinite > false (boolean) isFinite > true (boolean) isFinite > null (object)
""
(空文字列) true
, false
, null
はすり抜けてしまう。
Number.isFinite() (ES6)
checklist.forEach(function(v) { if( Number.isFinite(v) ) { console.log('Number.isFinite >', v, "("+typeof(v)+")"); } });
出力👇
Number.isFinite > 0 (number)
"0"
, "123"
のような文字列化しているものは弾かれてしまう。
Number.isInteger() (ES6)
型チェック込で整数かどうかを判別するので、少数や文字列になっているものも弾かれる。
Number.isFinite("0"); // false Number.isFinite(12.8); // false
数値と文字列化している数字のみチェックしたい
var checklist = [ 0, "0", "", undefined, "undefined", false, "false", true, "true", null, "null", NaN, "NaN", Infinity, "Infinity", -Infinity, "-Infinity", "123", -5, 12.8, "A" ]; var a = checklist.filter(function(val, i) { // 文字列になった数字も取り出したいので、isFinite() を使う // true, false がすり抜けてしまうので、`boolean` 型も弾く if( !isFinite(val) || typeof(val) === "boolean" ) { return false; } if( val-0 === 0 ) { // 暗黙の型変換で 0 になるものは 数字で構成されているかチェックする if(/[0-9]/g.test(val)) return true; } else { return true; } }); console.log(a); // [ 0, '0', '123', -5, 12.8 ]
暗黙の型変換で0
になるものだけ正規表現でチェックをしているので、そこまで実行速度に影響は無いとは思います。
条件式版も作ってみましたが、条件がこれでOKかちょっと不安があります…
var a = checklist.filter(function(val, i) { // 文字列になった数字も取り出したいので、isFinite() を使う // true, false がすり抜けてしまうので、`boolean` 型も弾く if( !isFinite(val) || typeof(val) === "boolean" ) { return false; } // 条件は本当にコレで大丈夫??? if( typeof(val) === 'number' || (typeof(val) === 'string' && val !== "") || val - 0 !== 0 ) { return true; } }); console.log(a); // [ 0, '0', '123', -5, 12.8 ]
感想
なんとか数字と文字列化した数字を判定することができました。
ゆるふわ型javascriptの暗黙の型変換ほんと鬼門です。
そう考えるとRubyのfalse
とnil
のときだけfalse
になる。って凄く便利なんですね!
[参考]
- isNaN() - JavaScript | MDN
- Number.isNaN() - JavaScript | MDN
- NaN をなんとかしたい上での諸注意 と global.isFinite() の罠 - Qiita
- isFinite() - JavaScript | MDN
- Number.isFinite() - JavaScript | MDN
- 作者: ダニエル・タメット,古屋美登里
- 出版社/メーカー: 講談社
- 発売日: 2014/06/13
- メディア: 文庫
- この商品を含むブログ (3件) を見る