jojotyping02【phina.js】

jojotypingでエラーが出たのでバグの解析。

エラー時の内容は以下

 

▷発生したエラー

app.js:67 Uncaught TypeError: Cannot read property 'indexOf' of undefined

undefindに対してindexOfというメソッド(JavaScriptのオブジェクトのプロパティが関数になっているもの)を参照しようとして読めなかった(そんなものは存在しない)というエラー。

 

▷エラー部分の実際のコード

this.mojiList.indexOf(mojiLabel);

mojiListの部分がundefindになっていた。(実際のコード67行目)
ここのthisはMainScene(クラス)のインスタンス(実体)を指しているはず。

ここで考えられる原因は2つ。

1:MainSceneのインスタンスにmojiListというプロパティが無い(最初から作られていないor何故か消えた)
2:実はthisがMainSceneのインスタンスとは違うオブジェクトを指していて、そこにmojiListというプロパティが無い

▷1について

phina.define('MainScene', {
  superClass: 'DisplayScene',

  init: function (option) {
    this.superInit(option);
    // this = MainSceneクラスのインスタンス

    this.mojiList = [];

最初から作られていない?
mojiListはここで作られているので、最初から作られていないことはありえない。
(MainSceneのインスタンスを作るときに必ず最初にinitが呼ばれる=作られる)

何故か消えた?
deleteを使わないと、一度作ったプロパティは消せないので消えることもありえない。
(プログラムの中で一度もdeleteを使っていない)

 

▷2について

mojiLabel.tweener
  .to({ x: this.width + 50 }, 4500)  //toは第一引数を目標にして値を変化(tweenerでのみ使える)
  .call(function () {
    mojiLabel.remove();   //callは第一引数の関数を呼び出す(tweenerでのみ使える)
    var index = this.mojiList.indexOf(mojiLabel);
    if (index >= 0) {
      this.mojiList.splice(index, 1);
    }
  });
this.mojiList.push(mojiLabel);

tweenerのメソッド(オブジェクトのプロパティになっている関数)であるcallは第一引数に指定したタイミングで実行したい関数を、第二引数に第一引数で渡した関数の中でthisになるオブジェクトを渡す。

※tweenerのtoやcallはtweenerの予定を記録する。
記録した内容は、並列実行(複数のプログラムが同時に動いているように見える)される。

※callは後で実行したい処理をfunctionにして渡す。(callback、callback関数という)

callは第二引数を省略するとthisがtweenerを指す仕様になっている。(phina.js仕様)
なので、この場合functionの中でthis.mojiList.indexOf(mojiLabel)のthisがtweenerを指している。
tweenerにmojiListというプロパティは存在しないので、undefind(未定義)となっている。
このundefindに対してさらにindexOfというプロパティを参照しようとしてエラーになった。

※存在しないプロパティを参照してもエラーにならない(JavaScript仕様)
この場合、mojiListのプロパティが存在せずundefindになっているがそれはエラーにはならず、undefindのプロパティを参照しようとしてエラーになる。

 

▷エラー修正

ここで使うthisはMainSceneのインスタンスを指していてほしいが、callに渡した関数の中ではthisの指す先が変わってしまう。
なので、あらかじめMainSceneのインスタンスを別の変数に渡しておく。

var self = this;

mojiLabel.tweener
  .to({ x: this.width + 50 }, 4500)  //toは第一引数を目標にして値を変化(tweenerでのみ使える)
  .call(function () {
    mojiLabel.remove();   //callは第一引数の関数を呼び出す(tweenerでのみ使える)
    var index = self.mojiList.indexOf(mojiLabel);
    if (index >= 0) {
      self.mojiList.splice(index, 1);
    }
  });

変数selfにthis(MainSceneのインスタンス)を代入する。
(call内のfunctionの外にあるthisはMainSceneのインスタンスを指している)

これで実行した結果、エラーは解消された。
(エラー=解消、不具合=改修と表現する・・・が、会社によって表現が違うらしい)

コメントを残す

あなたのメールアドレスは公開されません。必須項目には印がついています *