RPGツクールMVにおけるJavascriptの特殊な判定式の罠を事前に検知するスクリプト

## はじめに
はじめてのQiita投稿です。お手柔らかに……。
※編集・コメントありがとうございます。即適応させていただきました。
(作者: twitter @merusaia)

RPGツクールMVというツールは、エディタで出来ることもさることながら、
javascriptを使うことで、ツクール至上最も拡張性の高いものに仕上がっていると思います。

他のプログラミング言語を使ってゲームを作っていた人も、
「これはスクリプトを触れば色々出来るんじゃない？」と
ワクワク期待を膨らませられます（筆者はC#から移行してます）。

## 概要
ですが、CやJava方面から見ると、javascriptの各種判定式は、かなり特殊です。
他の言語と一緒に考えてたら、痛い目みます。。
詳しくは、それぞれのキーワードをぐぐってみてください。罠にハマります。

そこで、なるべくjavascriptの罠にはまらないように、
事前にツクールMVのエディタで、値や各種挙動をチェックできる
スクリプトを作りました。

## 使い方
ツクールMVのエディタ「スクリプト」で、以下の10行を貼り付けてください。
そして、【好きな初期値】に変数値を入れて、
右クリックメニューで「テスト」してください。

変数「_a」の判定式が、それぞれどんな反応が返ってくるか、事前にわかります。
まだ必要な判定がアレば、お気軽にご指摘・判定式の追加をお願いします。。

```js
var _a = 【好きな初期値】; // ここの「a = 」の後に【好きな初期値】を入れてね。
alert(
 "「var _a = 【好きな初期値】」の時の判定式だよ。"+"\n_aの値: "+_a
+"\n_a==0: " + (_a==0));
alert(
 "_a instanceof Number: " + (_a instanceof Number) +" // 「0 instanceof Number」はfalseだから、気をつけてね。new Number(0)はtrue。\n_a instanceof String: " + (_a instanceof String) + " //「”あ” instanceof String」はfalseだから、気をつけてね。「new String(”あ”)」はtrue。"
+"\n_a instanceof Object: " + (_a instanceof Object) +"\n_a instanceof Boolean: " + (_a instanceof Boolean)
+"\n_a==undefined: " + (_a==undefined) +"\n_a==null: " + (_a==null) + "\n_a===undefined: " + (_a===undefined) +"\n_a===null: " + (_a===null)
+"\n_a===NaN: " + (_a===NaN) +"\nNumber.isNaN(_a): " + Number.isNaN(_a) + "\nNumber.isFinate(_a): " + (Number.isFinite(_a)) + "\n_a === Infinity: " + (_a === Infinity)   + "\n_a === -Infinity: " + (_a === -Infinity)   
+"\nparseInt(_a): " + parseInt(_a) +"\n_a || 0: " + (_a || 0)       );
```

## 番外編：よく忘れる判定式の挙動　（他にもたくさんあるわな）
以下、自分用のメモの貼り付けで恐縮ですが、こんなのがあります。
エディタのコモンイベントなどに一括管理して、よく見返しております…。。
罠だらけだ…＞＜。


  ◆注釈：判定演算子、isNaN、Number.isNaN、「a || 0」などについてについて。
  ◆注釈：NaN === NaN　は falseです。。。仕様おかしい。。
  ：　　：NaN > 0 はfalseです。
  ：　　：NaN < 0 はfalseです。
  ：　　：NaN != null はtrueです。
  ：　　：NaNの判定には、Number.isNaN(a)を使います。isNaN(a)と書いちゃダメです。信頼性に欠けます。
  ◆スクリプト：if(NaN < 0){
  ：　　　　　： alert("数えられない数は0より小さいよ。ここは永久に実行されないから注意してね。");
  ：　　　　　：}else{
  ：　　　　　： alert("数えられない数は0より小さく…ないよ。知らないけど。");
  ：　　　　　：}
  ◆スクリプト：if(NaN > 0){
  ：　　　　　： alert("数えられない数は0より大きいよ。ここは永久に実行されないから注意してね。");
  ：　　　　　：}else{
  ：　　　　　： alert("数えられない数は0より大きく…ないよ。知らないけど。");
  ：　　　　　：}
  ◆スクリプト：if(NaN != 0){
  ：　　　　　： alert("数えられない数NaNは0じゃないよ。だから比較すらできないから、>や<は全部falseだよ。");
  ：　　　　　：}
  ◆スクリプト：if(NaN != null){
  ：　　　　　： alert("数えられない数NaNはnullでもundefinedでもないよ。だからNumber.isNaN()でちゃんと比較しないといけないよ。");
  ：　　　　　：}
  ◆スクリプト：if(isNaN('a')){
  ：　　　　　： alert("isNaN('a')は、falseだよ。"
  ：　　　　　：+"だって、数値"+Number(isNaN('a'))+"に変換できちゃうもんね～。や～いや～い、ひっかかった～（絶望）");
  ：　　　　　：}
  ◆スクリプト：if(Number.isNaN('a')){
  ：　　　　　： alert("ここは実行されないよ。");
  ：　　　　　：}else{
  ：　　　　　： alert("Number.isNaN('a')もfalseだよ。\n"
  ：　　　　　：+"文字列が入っている可能性があるときは、NaNか調べるときは、Number.isNaN(a)を使おうね。");
  ：　　　　　：}
  ◆スクリプト：var _num1 = NaN;
  ：　　　　　：_num1 -= 50;
  ：　　　　　：if(Number.isNaN(_num1)){
  ：　　　　　： alert("NaNなものに、何を演算しても、NaNのままだよ");
  ：　　　　　：}


  ◆注釈：■NaNの仕様がいろいろとよくわからない剣でぶっ刺されるについて
  ◆注釈：ここ、気をつけて。もはやわけわかめだよ‥。
  ◆スクリプト：alert(isFinite(NaN)); // falseです。NaNは数えられない数、比較すらできないんですから、当然ですよね。
  ◆スクリプト：alert(Number.isFinite(NaN)); // falseです。NaNは数えられない数、比較すらできないんですから、当然ですよね。
  ◆スクリプト：alert(isFinite(Infinity)); // falseです。無限は数えられない？　・・え？　そうです・・かね。
  ◆スクリプト：alert(Number.isFinite(Infinity)); // falseです。無限は数えられない。そうなんですね。
  ◆スクリプト：alert(Number.isFinite(undefined)); // falseです。そうですよね。
  ◆スクリプト：alert(isFinite(undefined)); // falseです。そうですよね。
  ◆スクリプト：alert(isFinite(null)); // trueです。。なぜに。。。
  ◆スクリプト：alert(Number.isFinite(null)); // falseです。そうですよね。
  ◆スクリプト：alert(isFinite("12")); // trueです。文字列のままでも、数えられるんだな、これが。
  ◆スクリプト：alert(Number.isFinite("12")); // falseです。Number.は、そういう卑劣なことは許しません。


  ◆注釈：ここ、気をつけて。もはやわけわかめだよ‥。
  ◆スクリプト：NaN === NaN    // falseを返す!!!
  ：　　　　　：function isReallyNaN(x) {
  ：　　　　　：  return x !== x;    // xがNaNであればtrue, それ以外ではfalse
  ：　　　　　：}
  ◆スクリプト：// 標準で用意されているisNaNにNaNを渡すと確かにtrueが返ります。
  ：　　　　　：// ただ、暗黙の型変換によって引数を数値へと変換してしまう為、NaN自身でなくても、NaNへと変換される類のものに対してもtrueを返してしまいます。
  ：　　　　　：// isNaNはNaNであるかの判定ではなく、引数が数値へ変換可能かどうかの判定に使われるみたいです。
  ：　　　　　：isNaN(NaN);                // true
  ：　　　　　：isNaN("foo");              // true
  ：　　　　　：isNaN(undefined);          // true
  ：　　　　　：isNaN({});                 // true
  ：　　　　　：isNaN({ valueOf: "foo" }); // true
  ：　　　　　：// 新しく作られたNumber.isNaNは、 x != x と同値です。
  ：　　　　　：Number.isNaN(NaN);   // true
  ：　　　　　：Number.isNaN('NaN'); // false
  ：　　　　　：alert(Number.isNaN(Infinity)); // false


  ◆注釈：javascriptでは、Boolean(a)は、
  ：　　：aが値が省略された場合や、値が 0, -0, null, false, NaN, undefined 
  ：　　：あるいは空文字列 ("") であった場合、false の初期値を持ちます。
  ：　　：それ以外のあらゆる値は、"false" という文字列も含めて、trueです。
  ◆スクリプト：alert(Boolean(NaN)); // false
  ◆スクリプト：alert(Boolean(false)); // false
  ◆スクリプト：alert(Boolean("false")); // true
  ◆スクリプト：alert(Boolean(Infinity)); // true


  ◆注釈：ここ、気をつけて。if(a)は、aがnull, undefinedの時だけじゃなく、0, ""、NaNの時もfalse だよ。
  ◆スクリプト：var a = '';
  ：　　　　　：alert(!!a); // if(a)がtrueかを返す。if('')はfalse。
  ：　　　　　：a = "";
  ：　　　　　：alert(!!a); // if(a)がtrueかを返す。if("")はfalse。
  ：　　　　　：a = 0;
  ：　　　　　：alert(!!a); // if(0)はfalse。
  ：　　　　　：a = "0";
  ：　　　　　：alert(!!a); // if("0")はtrue。
  ：　　　　　：a = " ";
  ：　　　　　：alert(!!a); // if(" ")はtrue。


  ◆注釈：「a || 0」という記述はよく見るけど、0、""、NaNの時も0になるよ。特に""が注意！
  ◆スクリプト：var a = Infinity;
  ：　　　　　：alert(!!a); // if(Infinity)はtrue。
  ：　　　　　：var a = NaN;
  ：　　　　　：alert(!!a); // if(NaN)はfalse。…ええ～～～！？？？？。
  ：　　　　　：
  ：　　　　　：// なるほど。だから以下は、NaNでも0になるのか。
  ：　　　　　：var a = a || 0;
  ：　　　　　：// 上の１行は、下の３行と同じ意味、ですよね。
  ：　　　　　：if(!a){
  ：　　　　　：  a = 0;
  ：　　　　　：}

皆さまもお気をつけて……。