このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
MixiError を Error から継承するためには、
MixiError のプロトタイプチェーンに
Error プロトタイプを追加すればよいことがわかった。
つまり、次のようなチェーンになれば良い。
MixiError インスタンス
⇒MixiError プロトタイプ
⇒Error プロトタイプ
⇒Object プロトタイプ
ただ、これは単純には実現できない。
MixiError プロトタイプは、既定では、
new Object() で作成される Object のインスタンスである。
(厳密には、constructor プロパティも自動的に設定される)
つまり、MixiError プロトタイプ⇒Object プロトタイプだ。
MixiError プロトタイプが、Object プロトタイプではなく、
Error プロトタイプを参照するように変えるには、
内部的な参照を書き換える必要があるが、
これはプログラムコードからアクセスすることができない。
では、どうすればよいか。
MixiError プロトタイプは、MixiError コンストラクタの
prototype プロパティに格納されている。
prototype プロパティは読み取り専用ではないので、
必要であれば、好きなオブジェクトを使うことができる。
なので、Error プロトタイプを参照するオブジェクトを、
MixiError プロトタイプとして使えばよいのだ。
そのようなオブジェクトとして最初に思いつくのは、
Error インスタンスである。
function MixiError(message) {
// 省略
}
MixiError.prototype = new Error(); // ダミー
MixiError.prototype.constructor = MixiError;
// name には例外型の名前が入る。
MixiError.prototype.name = "MixiError";
// その他のプロトタイププロパティの設定
MixiError.prototype.hoge = "fuga";
プロトタイプは、constructor プロパティを持ち、
値としてコンストラクタへの参照を保持しなければならない。
既定で作られる MixiError.prototype は、
適切な constructor プロパティを持つのだが、
今回は、プロトタイプ自体を置き換えているので、
改めて constructor プロパティへの代入が必要だ。
こうすると、以下のようなチェーンとなる。
MixiError インスタンス
⇒MixiError プロトタイプ(=Error インスタンス)
⇒Error プロトタイプ
⇒Object プロトタイプ
では試してみよう。
var instance = new MixiError("hogehoge");
WScript.Echo(instance.toString());
実行すると、[object Error] と表示された。
もし、Object プロトタイプの toString が呼ばれていたら、
[object Object] と表示されるはずなので、
Error プロトタイプの toString が呼ばれているのは確かだ。
これはうまくいっているように見える。
実際、MixiError 型には何も問題がない。
問題がどこにあるかというと、
Error インスタンスを作成しているという点だ。
たとえ MixiError インスタンスを利用しなかったとしても、
MixiError プロトタイプは存在するため、
余計な Error インスタンスが 1 つ作成されてしまうのだ。
Error 型は自分で作った型ではないので、
Error インスタンスがどんなプロパティを持つか分からない。
また、インスタンスを作成することによって、
どのような処理が行われるかどうかもわからない。
これは、例えば Error コンストラクタが、
自分のインスタンスの数を数えていたり、
例外を送出するために特別なコードを実行したりする場合、
目に見えないところで問題が起きる可能性が考えられる。
また、Error インスタンスがプロトタイプになっているので、
Error プロトタイプが持たず、
Error インスタンスのみが持つプロパティまで、
MixiError のプロトタイプとなってしまう。
例えば、FireFox の Error インスタンスは、
stack というプロパティを持つ。
これは例外が起きた場所を特定するための情報であり、
Error プロトタイプは、このプロパティを持っていない。
もし、MixiError を上記のように実装した場合、
Error インスタンスである MixiError プロトタイプが、
stack プロパティを持ってしまうことになり、
それは MixiError インスタンス全てに影響してしまうのだ。