35.NaNの謎
NaNってナンだ?
配列がらみになるのですが、ちょっと引っかかったところがあったので、そのあたりをまとめておきます。
上のオヤジギャグを書きたかっただけ、という話もありますが、、、?!
定義していない要素をいじる
配列を扱っていると定義していないのをうっかり計算に入れてしまうことってありません?
え?ない?だから、ここでない、って言ったら話がすすまないでしょ?ウソでも「そうですね」と答えるのが大人のやさしさってもんです。
では、基本的なところから確認してみます。
trace(array[0]);//0
trace(array[1]);//1
trace(array[2]);//undefined
array[2]は定義されていないのでundefinedとなるのはOKです。納得であります。
では、array[2]+=1とすれば?
演算があれば0として扱ってくれる、、、?
いえいえ、結果は以下のようになります。
array[2]+=1;
trace(array[2]);//NaN
さっきはundefinedだったのが、NaNになりました。
なんだかわかりませんが、とりあえず0として扱われることはないようです。
まあ納得ですね。
うっかり計算に入れてしまってるのだから、ここは変な値を返してほしいですからね。
ちなみにNaNは Not a Number のことだそうです。
Boolean型で評価すると
よく if (array[2]){ ってな感じでtrueかfalseかで評価することってありますよね。
先ほどの、undefinedだの、NaNだのはどうなるんでしょうか?
if (array[2]) {//array[2]はundefined
trace("true");
}else{
trace("false");//falseが表示されます
}
array[2]+=1;//これでNaN
if (array[2]) {
trace("true");
}else{
trace("false");//これもやっぱりfalseが表示されます
}
どちらも false になるのは、納得ですね。
0と区別するには?
上で中身がないのがfalseになるのはいいんですけど、0もfalseと評価されますよね。
よって、この配列に中身はあるのか?って評価するのに
//処理
}
という書き方はまずいことになります。0の場合に処理されませんので。
では、、、
//処理
}
まあこれでも用は足せますが、、、あんまり人に見られたくないですね(^^;
こういう便利な関数がありますのでこっちの方が恥ずかしくないかもしれません。
//処理
}
NaNを含んだ場合のソート
では、うっかりNaNを含む配列をソートしたら、という場合。
配列は値段(price)と名称(name)を持つオブジェクト形式とします。
array.push( {price:150 , name:"apple"} );
array.push( {price:100 , name:"banana"} );
array.push( {price:NaN , name:"chocolate"} );//チョコの値段はNaN
このように定義すると array[0].name とか array[1].price という感じでアクセスできますよね。
ここでは、テストのために3つめの chocolate の price を NaN と設定しています。
ではこれを price でソートして値を確認してみます。
array.sortOn("price" , Array.DESCENDING|Array.NUMERIC);
//確認
trace(array[0].name+" = "+array[0].price);//chocolate = NaN
trace(array[1].name+" = "+array[1].price);//apple = 150
trace(array[2].name+" = "+array[2].price);//banana = 100
え?
chocolate の NaN が一番高い???
値が小さい順でやっても chocolate が一番高いと評価されます。
このようなソートの対象に NaN を含む場合に一番値が大きいとするのがいいのか、いつもの如く(?)無言で停止するのがいいのか私にはわかりませんが、、、
なぜこうなるかは謎ですが、ともかく要注意であります。