ExtendScriptでは
false==null;
がtrueになるけど、変数を使って
x=false;
x==null;
とするとfalseになる(JavaScript的に正しいのはfalse)
っていう話をだいぶ前に書いたんですが(
これの8番目)
他にもnullと==で比較した結果がおかしいものを見つけました。
0, "0", "" です。("0"はfalsyですらないのに…)
似たような現象はこんなのでも起きます。
数値と文字列の比較では文字列側をNumberに変換するので、"!"はNaNになって、「NaNは比較演算子で何と比較してもfalseを返す」という性質があるので false になるはずなのですが、変数に入れずに直接比較すると true になってしまいます。変数がある場合は正しいです。
でー、変数があるかないかでなんでこんな違いが発生するのかなんですけど、
JSXBIN化を使ってみるとヒントめいたものが見えてきます。
これは「null==false;」をJSXBIN化した文字列
@JSXBIN@ES@2.0@MyBbyBn0ABJAnAFct0DzABByB
そしてこれは「true;」をJSXBIN化した文字列です。
@JSXBIN@ES@2.0@MyBbyBn0ABJAnAFct0DzABByB
完全に一致です。
これは比較演算だけでなく、「1+1」と「2」とかでも同じになります。
つまりはJSXBIN化(コンパイル)した時点で既に演算されてるのです。
変数のある演算は、実際にプログラムが動いてその行に行きつくまで結果がわからないけど、1+1とか0==nullみたいなプリミティブ値のリテラル同士の演算は最初から結果がわかってるので、高速化のためにもコンパイル時に演算しておこう、ということなんだと思います。
で、その演算が間違ってると。
ここまでは「値を直接演算するとおかしいけど、変数があれば正しい」というもので、実際のスクリプトで出てくるのはほぼ変数ありの演算でしょうから、まあ罠ではあるけどそんなに深刻なバグではありません。
次のは変数があろうとなかろうと、常におかしいやつです。
undefined < 任意の数
は、JavaScript的にはfalseになるのが正しいですが、
ExtendScriptではtrueになります。
たとえばこんなコードでうっかり引数を入れ忘れて実行したらtrueが返ってきてしまいます。
function f(x){
return x<0;
}
f();
ちなみに任意の数ってのは0とか100だけでなく、Infinityや-Infinityも含まれます。
「undefinedはマイナス無限大よりも小さい」ということになってしまうのです。
オワリ
PR