雑談:ツクールプラグインを作る時の話、nullチェック

MV雑談

RPGツクールMV/MZのプラグインを作る時の話です。

最初は誰でも、コアスクリプトや他のプラグインを真似して書くことになると思います。

今回は、真似をして書くとバグの原因になりがちな、要注意な書き方を2つ紹介します。

初心者向けの備忘録のようなものですので、書き慣れている方はスルーしてください。


要注意その1:undefined/nullチェック

JavaScriptにはundefind値というものがあります。変数を定義しただけで初期値を設定していない時、その変数を参照するとundefined値が返ります。この値はnullとはまた違う値です。違う値ですが、この値を計算に利用するとエラーになるという点では同じことです。

  • undefined:未設定であることを示す値。
  • null:変数のメモリを解放するため、異常を示すためなどの意図であえて設定した、値が存在しない状態を表すもの。

どちらの値も、登場したら特別な処理をするか、処理を終わらせたくなることが多いです。ですから、nullとundefinedを判定(以下、nullチェック)するのは大切なことです。

さて、ツクールのコアスクリプトを読むとこんな感じの記述が見つかります。

if (hensu) {
    // 処理
}
if (object) {
    // 処理
}

ifの中身が変数やプロパティ、それからオブジェクトや関数だけになっています。値を単体で判定している書き方です。この値がundefinedやnullなら処理が実行されませんから、一見するとnullチェックを簡潔に行っているように見えます。

しかしながら、これをnullチェックのつもりでそのまま真似して書くと間違います。

落ち着いて見直してみましょう。

if (hensu) {
    // 処理
}

やっていることは「if文による値の評価」です。値がundefinedやnullならfalseと判定してくれて良いのですが、値が数値のゼロや空文字列(""など)の場合もfalseとして判定されます

以下は、判定の際にfalseに変換される値です。

  • undefined
  • null
  • NaN(非数を表す値)
  • 0
  • 空文字列

ゼロも空文字列も、ちゃんと初期値を設定したような値ですよね。それがfalseになるので、間違いの元になりやすいです。

ですから、この書き方を真似する時には、「この場面ではゼロも空文字もあり得ない」あるいは「この場面ならゼロも空文字もfalseになって問題ない」という確信が必要です。

例えば判定する対象がウィンドウなどであれば、ゼロも空文字も気にしなくて良いでしょう。ウィンドウが生成済みか、まだ存在しないのかを判定できれば良いです。コアスクリプトでよく見るのが次のような書き方です。

if (goldWindow) {
    // 処理
}

こういう分かりやすいケースなら問題はありません。

しかし、自分で定義した変数や関数が相手だと、その値はゼロかもしれませんし空文字かもしれません。
そんな時にundefinedやnull「だけ」を判定したい場合にはどうすればいいかというと、if文で明記することです。

if (hensu == undefined) {
    // undefined、null処理
} else {
    // 通常処理(ゼロも空文字もこちら)
}

「==」を使うと曖昧判定となり、undefinedとnullを同じものとして判定できます。ですので「undefined」の部分を「null」と書いても同じことです。

他のプログラミング言語で書き慣れている、見慣れている方も多いでしょうから、nullで判定するほうが個人的には好みです。

if (hensu == null) {
    // undefined、null処理
} else {
    // 通常処理(ゼロも空文字もこちら)
}

次の書き方で、「値がある時だけ処理」とするケースは多いですね。

if (hensu != null) {
    //処理
}

ちなみにundefinedとnullを別物として、それぞれ厳密に判定したい場合は「===」「!==」を使います。

if (hensu === undefined) {
    // undefinedの処理
} else if (hensu === null) {
    // nullの処理
}

ユーザー向けにエラーメッセージを出す時などに使えますね。使ったことはないですが。


要注意その2:論理和演算子


コアスクリプトの中にはこんな記述もあります。

return value || 0;

「値がなければ初期値を返す」のような処理でしょうか……じっくり見ていきましょう。

論理和演算子「||」が使われていますね。この表記は通常、if文の条件式で出てきます。その場合、「もしくは」の意味で条件をつなぐ役目があります。

if (a === 0 || b === 0 || c === 0) {
    //処理
}

左に書かれてある条件から順に1つずつ評価し、trueだった時点で判定を打ち切って処理に進みます。

この論理和ですが、if文以外で、冒頭のような形で使用されると別の動作をします。どういう動作かというと、「左の値がtrueに変換できるならその値、できないなら右の値を返す」というもの。

trueに変換できるならと聞くと、「むむっ?」となるはずです。「その1」と同じことです。ゼロも空文字もfalse扱いになる点に注意が必要です。

return value || 0;

↑なら問題はなさそうですが、

return value || 1;

↑だと、ゼロが返ることは永遠にないわけです。値がゼロなら1が返ります。それが分かっていればいいのですが……。私は昔、こう書けば値がゼロならゼロが返るものと思い込んでいました。

ということで、ここもnullチェックだけをしたいなら、if文を書きましょう。

if (value == null) {
    return 1;
} else {
    return value;
}

行数が増えるのが嫌な時は三項演算子を使いましょう。if文を1行で表現できます。次の書式となります。

条件 ? 成立した時の式 : 成立しなかった時の式;

return value == null ? 1 : value;

次に挙げる記述も同じ意味ですが、初期値が最後にくる分、読みやすいかもしれません。

return value != null ? value : 1;

こちらのほうが「nullじゃなかったら」というのが読み取りやすくなりますね。


いかがでしたでしょうか。

nullチェックと論理和演算子は、初めてプラグイン制作に挑戦する方にとってはトラップみたいな記述かと思い、今回ピックアップしてお届けしました。

私が以前に書いたプラグイン、ゼロだとfalseになるということを分かっていないものが混じっている気がします。

ということで、皆さんもお気をつけ下さい。

ツクール 一覧に戻る

RPGツクール | MV雑談 | MZ雑談
コメントはまだありません

コメントを残す

メールアドレスが公開されることはありません。

RPGツクール
【MZ】追加スキルデータプラグイン

ツクールMZ向け。MITライセンスです。 ↓右クリックして対象を保存GABA_SkillDataEx …

RPGツクール
【MZ】スキル情報画面プラグイン

ツクールMZ向け。MITライセンスです。 ↓右クリックして対象を保存GABA_SceneSkillI …

RPGツクール
【MZ】メッセージ中のタグで名前表示プラグイン

ツクールMZ向け。MITライセンスです。 ↓右クリックして対象を保存GABA_SpeakerName …