アド企画 制作部
アド企画 制作部
 

Flash:ActionScript3.0 データ型・初期値・数値判定(NaN、parseInt、parseFloat)の覚え書き

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の体系的仕様は、無限大の表現などと共に1985年の IEEE 754 浮動小数点規格で標準が与えられている。

NaN - ウィキペディア https://ja.wikipedia.org/wiki/NaN

※ 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)) で取得した値の文字数は?
※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 
*/