<script type="text/javascript"> function initializeBase(derive, base, baseArgs) { base.apply(derive, baseArgs); for(prop in base.prototype) { var proto = derive.constructor.prototype; if(!proto[prop]) { proto[prop] = base.prototype[prop]; } } } // Memberクラスの定義 var Member = function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; }; Member.prototype.getName = function() { return this.lastName + " " + this.firstName; }; var SpecialMember = function(firstName, lastName, role) { initializeBase(this, Member, [firstName, lastName]); this.role = role; }; SpecialMember.prototype.isAdministrator = function(){ return (this.role == 'Administrator'); } var mem = new SpecialMember('祥浩', '山田', 'Administrator'); document.writeln('名前:' + mem.getName() + '<br/>'); document.writeln('管理者:' + mem.isAdministrator()+'<br/>');
クラスを「」にしているのは、「クラスもどき」であり、クラス定義とオブジェクト(インスタンス)生成というJavaやC++の概念と少し違うためである。
Memberクラスの一メソッドとしてgetName()を定義する方法は、inherit.htmlの例の他に、直接Memberの定義として
var Member = function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getName = function() { return this.lastName + " " + this.firstName; }; };
のようにもできる(5.1節)。しかし、メモリーを無駄に使うので、推奨しないテキストには書いてあることに注意(5.2節)
クラス定義の変数(プロパティ)に値を与えて引き継ぐには、initializedBaseの1行目
base.apply(derive, baseArgs);一般的には、
メソッド名.apply(オブジェクト名, メソッドに与える引数)でOK.
プロパティ(メソッド)群を引き継ぐために
for(prop in base.prototype) { var proto = derive.constructor.prototype; if(!proto[prop]) { proto[prop] = base.prototype[prop]; } }を行なっている。引き継ぐ側(derive、具体的にはmem)のprototypeとしてMemberのprototypeをひとつひとつコピーするのである。(constructorというのを付けなければならないのが、気づきにくい。)
試しに、次を実行してみる。
<meta charset="utf-8"> <script type="text/javascript"> function initializeBase(derive, base, baseArgs) { base.apply(derive, baseArgs); /* for(prop in base.prototype) { var proto = derive.constructor.prototype; if(!proto[prop]) { proto[prop] = base.prototype[prop]; } } */ } // Memberクラスの定義 var Member = function(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; /* prototypeを用いないメソッドの定義(オブジェクトで使用できる) メモリーを無駄に使うので、推奨しないテキストには書いてある */ this.getName = function() { return this.lastName + " " + this.firstName; }; }; /* Member.prototype.getName = function() { return this.lastName + " " + this.firstName; }; */ var SpecialMember = function(firstName, lastName, role) { initializeBase(this, Member, [firstName, lastName]); this.role = role; }; SpecialMember.prototype.isAdministrator = function(){ return (this.role == 'Administrator'); } var mem = new SpecialMember('祥浩', '山田', 'Administrator'); document.writeln('名前:' + mem.呼dgetName() + '<br/>'); document.writeln('管理者:' + mem.isAdministrator()+'<br/>'); document.writeln('姓: ' + mem.lastName); // 直接プロパティを参照する </script>
Memberの定義に直接getName()を書きこんであるので、問題なく実行できる。
しかし、prototypeで定義したテキストの例では、mem.getName()は未定義だよというエラーになる。
initializedBase()の中に
document.writeln(derive.constructor);のように、constructorに何が入っているかを出力してみよう。 (文字列として、deriveの定義自体が入っていることがわかる。)