2013-05-13 7 views
6

ネイティブオブジェクトを使用して、Javascriptでコンストラクタチェーンの継承について何か不足しているようです。たとえば、次のようにネイティブオブジェクトからの継承

function ErrorChild(message) { Error.call(this, message); } 
ErrorChild.prototype = Object.create(Error.prototype); 
var myerror = new ErrorChild("Help!"); 

myerror.messageは、これらのステートメントの後に""として定義されるのはなぜ?私はErrorコンストラクタが "Help!"と定義することを期待しています。私がやっていたかのように、(とError.prototype.messageのデフォルト値を上書き):

var myerror = new Error("Help!") 

おかげでたくさん!簡単な回避策

答えて

4

Working fiddle

function ErrorChild(name, message) { 
    // Error.call(this); this is not needed 
    this.name = name; 
    this.message = message; 
} 

ErrorChild.prototype = Object.create(Error.prototype); 
ErrorChild.prototype.constructor = ErrorChild; 

var myerror = new ErrorChild("test", "Help!"); 
document.body.innerHTML += myerror.message; 

上記期待される動作を中断されません。 throw myerrorの場合、正しいnamemessageが表示されます。

ECMA5言語仕様から問題

15.11.1関数として呼び出すエラーコンストラクタエラーを関数としてではなく、コンストラクタと呼ばれている

は新しいErrorオブジェクトを作成して初期化します。したがって、関数呼び出し エラー(...)は、オブジェクト作成式new と同じ引数を持つエラー(...)と同等です。

問題:Error.call(this)は、new Errorに相当します。しかし、new Errorインスタンス化ではnameまたはmessageは設定されません。 new Errorは、デフォルトでmessage""に初期化します。

15.11.4.3 Error.prototype.message#ⓉоError.prototype.messageの初期値は、空のStringです。

テストproof

内側であれば、あなたのErrorChild追加しました:

var test = Error.call(this, message); 
console.dir(test); 
console.log(test instanceof Error); // true; 
console.log(test.message); // "Help!"; 

testがECMA5仕様を反映しています。適切なmessageが設定されたErrorインスタンス。

結論:

Error.call(arguments);自動的new Error(arguments);範囲に翻訳さなのでが失われ、その性質はthisオブジェクトに初期化されることはありません。

Object.create(Error.prototype)を使用すると、messageプロパティはデフォルト値の空のStringをとります。

+0

問題は、(HTTP [ '関数としてERROR'を呼び出す]ということです - あなたはthrow周りlogcatchでき

.io /#x15.11.1)はコンストラクタを呼び出すように振る舞います( 'new Error')。 – C5H8NNaO4

+0

あなたは答えを更新して問題を説明するのを待っていました。 D – C5H8NNaO4

+0

ええ、あなたの編集が10秒後に私の回答に気付いた^^(これは+1)、確かに面白い質問*(すでに何度か尋ねられましたが)* コミュニティーウィキwoldこのような質問(これをcwとして欺くのはなぜですか?) ええ、しかし、私は彼らがかなり良い問題をカバーすると思います。 =) – C5H8NNaO4

1

問題はない継承チェーンではなく、事実であること

したがってnew Errorオブジェクトを、コンストラクタを呼び出すインスタンスとしてcalling Error as a function振る舞う呼び出すときに、あなたのnew ErrorChild実行されるコードは、実際には同等の

function ErrorChild(message) { 
new Error (message) 
} 
にあります

待ちます。しかし、これは、ではないという新しいエラーオブジェクトを作成します。(コンストラクタによって返されません)。そして、単に忘れてしまいます。

実際にはではありません。実際のErrorChildインスタンスを変更します。

は、したがって、あなたがアクセスしているmessage propertieがError.protyotypeから継承ErrorChild.prototypeの影一つであり、したがって、含まれていmessageデフォルト値空の文字列""

しかし、単にあなたができる 『模倣』エラーオブジェクト。

あなたが唯一のエラーの標準プロパティをカバーするためにtoString method's defined behaviourと2プロパティ

  • name
  • message

を必要としたよう。

コンストラクタプロトタイプをError.prototype に設定して、namemessageを手動で割り当てることができます。

function ErrorChild (name,message) { 
    this.name = name; 
    this.message = message; 
} 
ErrorChild.prototype = Error.prototype; 

これで、new ErrorChild (...)インスタンスを作成できます。 //es5.github:>

throw new ErrorChild("CustomError","Help") //Uncaught CustomError: Help

相続人JSBin Demo