Flash:ActionScript3.0 データ型・初期値・数値判定(NaN、parseInt、parseFloat)の覚え書き
ActionScript3.0で、スクリプトを色々書いていて
『関数を定義した時、引数で数値を受け取って…引数が無かった場合の初期値は…「0」は「isNaN」で「false」を返すよなぁ…』
とか、わかってはいるはずの事で、たまに頭がこんがらがってきてしまいました。
ほら、なんか知っている漢字をじーーっと見ていると、「あれ? なんか…あれ? 合ってる? この漢字?」ってなったりしませんか?
そんな感じです(ならない人はスルーでお願いします)。
AS3である変数の数値判定をしたいと思ったらどうするんだ?
- 変数がデータ型を指定して定義されているだけの場合(初期値)
- 変数がデータ型も指定されずに定義されているだけの場合(var val:*)
- 変数がundefined、null…など、数値やString型でない場合
- isNaN()やparseInt()は、変な型を受け取った場合、ホントにエラーで止まらないのか?
こんな事をテストしてみましたので、今回はその結果をメモしておきます。
結論としては、
- isNaN()やparseInt()に色んなデータ型を渡しても、それ自体のエラーで止まるという事はないですね
- isNaN(null)がfalseを返すので、『isNaN(parseInt(val)) == 数値ではない』又は『isNaN(parseFloat(val)) == 数値ではない』で間違いなさそうですね
- parseInt()、parseFloat()は、先頭文字が数字だと数値を返してしまうので、『isNan(parseInt(val)) && String(parseInt(val)).length && String(val).length』又は『isNan(parseFloat(val)) && String(parseFloat(val)).length && String(val).length』として、
文字数の判定も…つけるべき?
という再確認になりました。
AS3:「NaN」とparseInt()、parseFloat() のお話し
「NaN」は「Not a Number」の「NaN」だそうです。
「NaN」は数値じゃないよ、なので「isNaN()」では「数値ですか?」ではなくて「数値ではないですか?」という判定が 「true」「false」で返ってくるわけです。
NaN(Not a Number、非数、ナン)は、コンピュータにおいて、主に浮動小数点演算の結果として、不正なオペランドを与えられたために生じた結果を表す値またはシンボルである。
NaN - ウィキペディア https://ja.wikipedia.org/wiki/NaN
NaNの体系的仕様は、無限大の表現などと共に1985年の IEEE 754 浮動小数点規格で標準が与えられている。
※ isNaN() のリファレンス
http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/package.html#isNaN()
また、parseIntは文字列から整数(1とか2とか)を、parseFloatは浮動小数点数(1.5とか2.3とか)を取得します。
ただ、文字列の先頭が数値だと、その数値を返してしまいます。
※ parseInt() のリファレンス
http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/package.html#parseInt()
※ parseFloat() のリファレンス
http://help.adobe.com/ja_JP/FlashPlatform/reference/actionscript/3/package.html#parseFloat()
AS3:データ型・値別のテストコード
テストしてみたのは、こんな感じのコードです。
数値の「0」「1」と、文字列の「2」、その他に「null」や「undefined」「NaN」をテストの対象にして、if文の判定結果を条件と一緒にトレース(出力)させてみました。
ifの条件(テスト)は、次の様にしてみました。
- 単純に「if(arg)」でtrueかfalseか
- 「undefiled == arg」 でtrueかfalseか
- 「isNaN(arg)」 でtrueかfalseか
- 「parseInt(arg)」 で何を返すか
- 「isNaN(parseInt(arg))」 でtrueかfalseか
falseなら、さらに- String(arg) で、argの値の文字数は?
- String(parseInt(arg)) で取得した文字列の文字数は?
- 「isNaN(parseFloat(arg))」 でtrueかfalseか
falseなら、さらに
- String(arg) で、argの値の文字数は?
- String(parseFloat(arg)) で取得した値の文字数は?
var arr: Array = [0, 1, "2", "3test", "te4st", 5.0, 6.1, "7.0", "8.1", null, undefined, NaN]; var val: * ; for each(val in arr) { trace(test(val)); } function test(arg: * = undefined): String { var str: String = "arg == " + arg + "\n"; if (arg is String) { str += "arg is String \n"; } if (arg) { str += "if(arg *) --- true \n"; } else { str += "if(arg *) --- false \n"; } if (arg == undefined) { str += "if(arg == undefined) --- true \n"; } else { str += "if(arg == undefined) --- false \n"; } if (isNaN(arg)) { str += "if(isNaN(arg)) --- true \n"; } else { str += "if(isNaN(arg)) --- false \n"; } str += "paseInt(arg) == " + parseInt(arg) + "\n"; if (isNaN(parseInt(arg))) { str += "if(isNaN(parseInt(arg)) --- true \n"; } else { str += "if(isNaN(parseInt(arg)) --- false \n"; str += "arg.toString.length --- " + String(arg).length+ "\n"; str += "String(parseInt(arg)).length --- " + String(parseInt(arg)).length+ "\n"; } str += "paseFloat(arg) == " + parseFloat(arg) + "\n"; if (isNaN(parseFloat(arg))) { str += "if(isNaN(parseFloat(arg)) --- true \n"; } else { str += "if(isNaN(parseFloat(arg)) --- false \n"; str += "String(arg).length --- " + String(arg).length+ "\n"; str += "String(parseFloat(arg)).length --- " + String(parseFloat(arg)).length+ "\n"; } return str; }
AS3:データ型・値別のテスト結果
テスト結果の出力は、次のとおり。
isNaN(null)がfalseを返すに、何かイラッとします。
また、「3test」という文字列は parseInt() も parseFloat() も「3」を返してきます。
ということは、正確にチェックするなら
『isNan(parseInt(val)) && String(parseInt(val)).length == String(val).length』又は
『isNan(parseFloat(val)) && String(parseFloat(val)).length == String(val).length』として、
もっとスッキリチェックできる方法、ありますか?
/* 出力 arg == 0 if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 0 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 0 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 1 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 1 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 2 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 2 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 2 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 3test arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == 3 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 5 String(parseInt(arg)).length --- 1 paseFloat(arg) == 3 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 5 String(parseFloat(arg)).length --- 1 arg == te4st arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == 5 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 5 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 5 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 6.1 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 6 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 6.1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 3 arg == 7.0 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 7 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 7 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 1 arg == 8.1 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 8 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 8.1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 3 arg == null if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- false paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == undefined if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == NaN if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true */
AS3:データ型・値別のおまけテストコード
isNaN()やparseInt()に変な型が渡ってしまったときは、エラーで止まるかしら(ホントに止まんないのかしら)?
という事で、引き続きテスト。
同じテストの関数で、Objectなんかも渡してみました。
trace("おまけ"); trace(""); var numval: Number; var intval: int; var strval: String; var testval: *; var obj:Object = {numval:numval, intval:intval, strval:strval, testval:testval}; var k:String; for(k in obj) { trace("arg name [" + k + "]"); trace(test(obj[k])); } trace("さらにオマケ"); trace(""); trace("arg name [obj]"); trace(test(obj));
AS3:データ型・値別のおまけテスト結果
テスト結果の出力は、次のとおり。
特に「エラーで止まる」という事はなく、テストは完了しました。
ちなみに、今回は関数の引数で「arg:*」として型を固定しないようにして処理しているので止まりませんが、
var val:String = "1";
var num:int = 1;
isNaN(val);
parseInt(num);
なんてすると、
『型intの値が、関連しない型Stringに暗黙で型変換されます』『型Stringの値が、関連しない型intに暗黙で型変換されます』
といった、型変換でコンパイルエラーが発生して止まったりします。
/* 出力 おまけ arg name [numval] arg == NaN if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg name [testval] arg == undefined if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg name [intval] arg == 0 if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 0 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 0 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg name [strval] arg == null if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- false paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true さらにオマケ arg name [obj] arg == [object Object] if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true */
今回のテストコード全部
function test(arg: * = undefined): String { var str: String = "arg == " + arg + "\n"; if (arg is String) { str += "arg is String \n"; } if (arg) { str += "if(arg *) --- true \n"; } else { str += "if(arg *) --- false \n"; } if (arg == undefined) { str += "if(arg == undefined) --- true \n"; } else { str += "if(arg == undefined) --- false \n"; } if (isNaN(arg)) { str += "if(isNaN(arg)) --- true \n"; } else { str += "if(isNaN(arg)) --- false \n"; } str += "paseInt(arg) == " + parseInt(arg) + "\n"; if (isNaN(parseInt(arg))) { str += "if(isNaN(parseInt(arg)) --- true \n"; } else { str += "if(isNaN(parseInt(arg)) --- false \n"; str += "arg.toString.length --- " + String(arg).length+ "\n"; str += "String(parseInt(arg)).length --- " + String(parseInt(arg)).length+ "\n"; } str += "paseFloat(arg) == " + parseFloat(arg) + "\n"; if (isNaN(parseFloat(arg))) { str += "if(isNaN(parseFloat(arg)) --- true \n"; } else { str += "if(isNaN(parseFloat(arg)) --- false \n"; str += "String(arg).length --- " + String(arg).length+ "\n"; str += "String(parseFloat(arg)).length --- " + String(parseFloat(arg)).length+ "\n"; } return str; } var arr: Array = [0, 1, "2", "3test", "te4st", 5.0, 6.1, "7.0", "8.1", null, undefined, NaN]; var val: * ; for each(val in arr) { trace(test(val)); } /* 出力 arg == 0 if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 0 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 0 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 1 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 1 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 2 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 2 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 2 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 3test arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == 3 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 5 String(parseInt(arg)).length --- 1 paseFloat(arg) == 3 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 5 String(parseFloat(arg)).length --- 1 arg == te4st arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == 5 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 5 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 5 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg == 6.1 if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 6 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 6.1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 3 arg == 7.0 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 7 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 7 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 1 arg == 8.1 arg is String if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 8 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 3 String(parseInt(arg)).length --- 1 paseFloat(arg) == 8.1 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 3 String(parseFloat(arg)).length --- 3 arg == null if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- false paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == undefined if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg == NaN if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true */ trace("おまけ"); trace(""); var numval: Number; var intval: int; var strval: String; var testval: * ; var obj: Object = { numval: numval, intval: intval, strval: strval, testval: testval }; var k: String; for (k in obj) { trace("arg name [" + k + "]"); trace(test(obj[k])); } trace("さらにオマケ"); trace(""); trace("arg name [obj]"); trace(test(obj)); /* 出力 おまけ arg name [numval] arg == NaN if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg name [testval] arg == undefined if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true arg name [intval] arg == 0 if(arg *) --- false if(arg == undefined) --- false if(isNaN(arg)) --- false paseInt(arg) == 0 if(isNaN(parseInt(arg)) --- false arg.toString.length --- 1 String(parseInt(arg)).length --- 1 paseFloat(arg) == 0 if(isNaN(parseFloat(arg)) --- false String(arg).length --- 1 String(parseFloat(arg)).length --- 1 arg name [strval] arg == null if(arg *) --- false if(arg == undefined) --- true if(isNaN(arg)) --- false paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true さらにオマケ arg name [obj] arg == [object Object] if(arg *) --- true if(arg == undefined) --- false if(isNaN(arg)) --- true paseInt(arg) == NaN if(isNaN(parseInt(arg)) --- true paseFloat(arg) == NaN if(isNaN(parseFloat(arg)) --- true */
