1. ホーム
  2. ジャバスクリプト

[解決済み】JavaScriptでカスタムErrorを作成する方法は?

2022-04-01 03:29:39

質問

以下のスニペットでは、なぜかコンストラクタのデリゲーションがうまくいかないようです。

function NotImplementedError() { 
  Error.apply(this, arguments); 
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")

これを実行すると The message is: '' . その理由や、新しい Error のサブクラスを作成できますか?に問題があるのでしょうか? apply をネイティブの Error のコンストラクタは、私が知らないのでしょうか?

どのように解決するのですか?

Error.prototypeにプロトタイプを代入し、instanceofを指定すると、アサートが機能するようにコードを更新してください。

function NotImplementedError(message = "") {
    this.name = "NotImplementedError";
    this.message = message;
}
NotImplementedError.prototype = Error.prototype;

しかし、私なら自分のオブジェクトを投げて、nameプロパティをチェックするだけにします。

throw {name : "NotImplementedError", message : "too lazy to implement"}; 

コメントを元に編集

コメントを見て、なぜプロトタイプを Error.prototype ではなく new Error() でNicholas Zakasが行ったような 記事 を作成しました。 jsFiddle を以下のようなコードで記述します。

function NotImplementedError(message = "") {
  this.name = "NotImplementedError";
  this.message = message;
}
NotImplementedError.prototype = Error.prototype;

function NotImplementedError2(message = "") {
  this.message = message;
}
NotImplementedError2.prototype = new Error();

try {
  var e = new NotImplementedError("NotImplementedError message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

try {
  var e = new NotImplementedError2("NotImplementedError2 message");
  throw e;
} catch (ex1) {
  console.log(ex1.stack);
  console.log("ex1 instanceof NotImplementedError2 = " + (ex1 instanceof NotImplementedError2));
  console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
  console.log("ex1.name = " + ex1.name);
  console.log("ex1.message = " + ex1.message);
}

コンソール出力はこのようになっていました。

undefined
ex1 instanceof NotImplementedError = true
ex1 instanceof Error = true
ex1.name = NotImplementedError
ex1.message = NotImplementedError message
Error
    at window.onload (http://fiddle.jshell.net/MwMEJ/show/:29:34)
ex1 instanceof NotImplementedError2 = true
ex1 instanceof Error = true
ex1.name = Error
ex1.message = NotImplementedError2 message

これは、私が遭遇したquot;問題"は、エラーのスタックプロパティが、以下の行番号であったことを確認します。 new Error() が作成された場所ではなく throw e が発生しました。 しかし、そのほうが NotImplementedError.prototype.name = "NotImplementedError" 行がErrorオブジェクトに影響を与えます。

また NotImplementedError2 を設定しない場合 .name を明示的に指定すると、"Error" になります。 しかし、コメントにもあるように、そのバージョンではprototypeに new Error() を設定することができます。 NotImplementedError2.prototype.name = "NotImplementedError2" でOKです。