prototype.js使って作ったクラスの属性の初期化

参照を持つ属性はinitialize関数の中で初期化しないと駄目なんすね。

<html>
  <head>
    <script src="prototype-1.6.0.2.js"></script>
    <script>
      /*
       * この定義はよくない
       */
      (Ng=Class.create()).prototype = {
        initialize: function() {},
        arr: [0, 0]
      };
      Ng.test = function() {
        var ng1 = new Ng();
        var ng2 = new Ng();

        // 異なるインスタンスの属性なのに、同一性チェックでtrueが返される
        alert(ng1.arr == ng2.arr); // => true

        // つまりこういう困ったことになる
        ng1.arr[0] = 100;
        alert(ng2.arr[0]); // => 100
      };

      /*
       * この定義は大丈夫
       */
      (Ok=Class.create()).prototype = {
        initialize: function() { this.arr = [0, 0] },
        arr: null
      };
      Ok.test = function() {
        var ok1 = new Ok();
        var ok2 = new Ok();

        // こちらは正しくfalseが返る
        alert(ok1.arr == ok2.arr); // => false

        // もちろんこれも大丈夫
        ok1.arr[0] = 100;
        alert(ok2.arr[0]); // => 0
      };
    </script>
  </head>
  <body>
    <button onclick="javascript:Ng.test()">Ng</button>
    <button onclick="javascript:Ok.test()">Ok</button>
  </body>
</html>


もちろんインスタンス変数の値が配列じゃなくてオブジェクトでも同じこと

<html>
  <head>
    <script src="prototype-1.6.0.2.js"></script>
    <script>
      (Value=Class.create()).prototype = {
        initialize: function() {},
        message: 'default' 
      };
      (Ng=Class.create()).prototype = {
        initialize: function() {},
        val: new Value() // これ駄目
      };
      (Ok=Class.create()).prototype = {
        initialize: function() {this.val = new Value()}, // これOK
        val: null
      };

      Event.observe(window, 'load', function() {
        var ng1 = new Ng();
        var ng2 = new Ng();
        ng1.val.message = 'updated';
        alert('ng2.val.message = ' + ng2.val.message); // => 'updated'

        var ok1 = new Ok();
        var ok2 = new Ok();
        ok1.val.message = 'updated';
        alert('ok2.val.message = ' + ok2.val.message); // => 'default'
      });
    </script>
  </head>
  <body>
  </body>
</html>