web-dev-qa-db-ja.com

JavaScriptのエラーを拡張する良い方法は何ですか?

私はJSコードにいくつかのものを投げて、それらをinstanceof Errorにしたいのですが、私はそれらを別のものにしたいのです。

Pythonでは、通常、Exceptionをサブクラス化します。

JSで適切なことは何ですか?

326
Josh Gibson

Errorオブジェクトが持つ唯一の標準フィールドは、messageプロパティです。 ( MDN 、またはEcmaScript言語仕様、セクション15.11を参照)他のすべてはプラットフォーム固有です。

ほとんどの環境はstackプロパティを設定しますが、fileNameおよびlineNumberは、継承で使用するのに実際には役に立ちません。

したがって、最小限のアプローチは次のとおりです。

function MyError(message) {
    this.name = 'MyError';
    this.message = message;
    this.stack = (new Error()).stack;
}
MyError.prototype = new Error;  // <-- remove this if you do not 
                                //     want MyError to be instanceof Error

スタックをスニッフィングし、不要な要素のシフトを解除してfileNameやlineNumberなどの情報を抽出できますが、そのためにはJavaScriptが現在実行されているプラ​​ットフォームに関する情報が必要です。ほとんどの場合、これは不要です。本当に必要な場合は、事後分析で行うことができます。

Safariは注目に値する例外です。 stackプロパティはありませんが、throwキーワードは、スローされているオブジェクトのsourceURLおよびlineプロパティを設定します。それらは正しいことが保証されています。

私が使用したテストケースは、ここにあります: JavaScriptの自作のエラーオブジェクト比較

190
Tero

ES6の場合:

class MyError extends Error {
  constructor(message) {
    super(message);
    this.name = 'MyError';
  }
}

ソース

130
Mohsen

編集:コメントを読んでください。これは、V8(Chrome/Node.JS)でのみ機能することがわかりました。私の意図は、すべてのブラウザーで機能するクロスブラウザーソリューションを提供し、サポートがある場所でスタックトレースを提供することでした。

編集:さらに編集できるように、このコミュニティWikiを作成しました。

V8(Chrome/Node.JS)のソリューションは、Firefoxで動作し、IEでほぼ正しく機能するように変更できます。 (投稿の終わりを参照)

function UserError(message) {
  this.constructor.prototype.__proto__ = Error.prototype // Make this an instanceof Error.
  Error.call(this) // Does not seem necessary. Perhaps remove this line?
  Error.captureStackTrace(this, this.constructor) // Creates the this.stack getter
  this.name = this.constructor.name; // Used to cause messages like "UserError: message" instead of the default "Error: message"
  this.message = message; // Used to set the message
}

「Show me the code!」に関するオリジナル投稿

短縮版:

function UserError(message) {
  this.constructor.prototype.__proto__ = Error.prototype
  Error.captureStackTrace(this, this.constructor)
  this.name = this.constructor.name
  this.message = message
}

関数内にthis.constructor.prototype.__proto__ = Error.prototypeを保持して、すべてのコードをまとめます。ただし、this.constructorUserErrorに置き換えることもできます。これにより、コードを関数の外部に移動できるため、1回だけ呼び出されます。

そのルートに行く場合は、UserErrorを最初にスローするときに、必ずその行beforeを呼び出してください。

関数は順序に関係なく最初に作成されるため、その警告は関数を適用しません。したがって、問題なくファイルの末尾に関数を移動できます。

ブラウザの互換性

FirefoxおよびChrome(およびNode.JS)で動作し、すべての約束を満たします。

Internet Explorerが以下で失敗する

  • エラーには最初からerr.stackがないので、「それは私のせいではありません」。

  • Error.captureStackTrace(this, this.constructor)は存在しないため、次のような何かをする必要があります

    if(Error.captureStackTrace) // AKA if not IE
        Error.captureStackTrace(this, this.constructor)
    
  • toStringをサブクラス化すると、Errorは存在しなくなります。したがって、追加する必要もあります。

    else
        this.toString = function () { return this.name + ': ' + this.message }
    
  • IEは、instanceof Errorを実行する前に以下を実行しない限り、UserErrorthrow UserErrorと見なしません。

    UserError.prototype = Error.prototype
    
43
Bryan Field

要するに:

  • トランスパイルなしでES6を使用している場合

    class CustomError extends Error { /* ... */}
    
  • Babel transpilerを使用している場合:

オプション1: babel-plugin-transform-b​​uiltin-extend を使用

オプション2:自分でやる(同じライブラリからヒントを得た)

    function CustomError(...args) {
      const instance = Reflect.construct(Error, args);
      Reflect.setPrototypeOf(instance, Reflect.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    Reflect.setPrototypeOf(CustomError, Error);
  • pure ES5を使用している場合:

    function CustomError(message, fileName, lineNumber) {
      var instance = new Error(message, fileName, lineNumber);
      Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
      return instance;
    }
    CustomError.prototype = Object.create(Error.prototype, {
      constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (Object.setPrototypeOf){
        Object.setPrototypeOf(CustomError, Error);
    } else {
        CustomError.__proto__ = Error;
    }
    
  • 代替: Classtrophobic frameworkを使用

説明:

ES6とBabelを使用してErrorクラスを拡張するのが問題なのはなぜですか?

これは、CustomErrorのインスタンスがそのように認識されなくなったためです。

class CustomError extends Error {}
console.log(new CustomError('test') instanceof Error);// true
console.log(new CustomError('test') instanceof CustomError);// false

実際、Babelの公式ドキュメントから、 組み込みJavaScriptクラスを拡張することはできませんDateArrayDOMErrorなど)を使用します。

問題は次のとおりです。

他のSO回答はどうですか?

与えられた答えはすべてinstanceofの問題を修正しますが、通常のエラーconsole.logを失います:

console.log(new CustomError('test'));
// output:
// CustomError {name: "MyError", message: "test", stack: "Error↵    at CustomError (<anonymous>:4:19)↵    at <anonymous>:1:5"}

上記の方法を使用すると、instanceofの問題を修正するだけでなく、通常のエラーconsole.logも保持されます。

console.log(new CustomError('test'));
// output:
// Error: test
//     at CustomError (<anonymous>:2:32)
//     at <anonymous>:1:5
36
JBE

ボイラープレートを避けるさまざまなタイプのエラーごとに、いくつかのソリューションの知恵をacreateErrorType関数に結合しました。

function createErrorType(name, init) {
  function E(message) {
    if (!Error.captureStackTrace)
      this.stack = (new Error()).stack;
    else
      Error.captureStackTrace(this, this.constructor);
    this.message = message;
    init && init.apply(this, arguments);
  }
  E.prototype = new Error();
  E.prototype.name = name;
  E.prototype.constructor = E;
  return E;
}

その後、新しいエラータイプを簡単に定義次のようにできます。

var NameError = createErrorType('NameError', function (name, invalidChar) {
  this.message = 'The name ' + name + ' may not contain ' + invalidChar;
});

var UnboundError = createErrorType('UnboundError', function (variableName) {
  this.message = 'Variable ' + variableName + ' is not bound';
});
26
Ruben Verborgh

2018では、これが最良の方法だと思います。 IE9 +および最新のブラウザーをサポートします。

UPDATE:異なる実装での比較については、 this test および repo を参照してください。

function CustomError(message) {
    Object.defineProperty(this, 'name', {
        enumerable: false,
        writable: false,
        value: 'CustomError'
    });

    Object.defineProperty(this, 'message', {
        enumerable: false,
        writable: true,
        value: message
    });

    if (Error.hasOwnProperty('captureStackTrace')) { // V8
        Error.captureStackTrace(this, CustomError);
    } else {
        Object.defineProperty(this, 'stack', {
            enumerable: false,
            writable: false,
            value: (new Error(message)).stack
        });
    }
}

if (typeof Object.setPrototypeOf === 'function') {
    Object.setPrototypeOf(CustomError.prototype, Error.prototype);
} else {
    CustomError.prototype = Object.create(Error.prototype, {
        constructor: { value: CustomError }
    });
}

また、__proto__プロパティは 非推奨 であり、他の回答で広く使用されていることに注意してください。

25

Node.jsを使用していて、ブラウザの互換性を気にする必要がない場合、以前の回答のどれもこのメソッドについて言及していなかったという理由だけで、完全を期すために、ビルトインで望ましい効果を達成するのは非常に簡単ですinheritsモジュールのutil公式ドキュメントはこちら )。

たとえば、最初の引数としてエラーコードを受け取り、2番目の引数としてエラーメッセージを受け取るカスタムエラークラスを作成するとします。

ファイルcustom-error.js

'use strict';

var util = require('util');

function CustomError(code, message) {
  Error.captureStackTrace(this, CustomError);
  this.name = CustomError.name;
  this.code = code;
  this.message = message;
}

util.inherits(CustomError, Error);

module.exports = CustomError;

これで、CustomErrorをインスタンス化してパス/スローできます。

var CustomError = require('./path/to/custom-error');

// pass as the first argument to your callback
callback(new CustomError(404, 'Not found!'));

// or, if you are working with try/catch, throw it
throw new CustomError(500, 'Server Error!');

このスニペットを使用すると、スタックトレースには正しいファイル名と行が含まれ、エラーインスタンスには正しい名前が付けられます。

これは、captureStackTraceメソッドの使用が原因で発生します。このメソッドは、ターゲットオブジェクトにstackプロパティを作成します(この場合、インスタンス化されるCustomError)。仕組みの詳細については、ドキュメントを確認してください here

19

クレセントフレッシュの高い投票による答えは誤解を招きます。彼の警告は無効ですが、彼が対処していない他の制限があります。

まず、Crescentの「警告:」段落の推論は意味をなしません。説明は、「if(error instanceof MyError)else ...の束」のコーディングは、複数のcatchステートメントと比較して、やや面倒または冗長であることを意味します。単一のcatchブロック内の複数のinstanceofステートメントは、複数のcatchステートメントと同じくらい簡潔です-トリックなしでクリーンで簡潔なコード。これは、Javaの優れたスロー可能サブタイプ固有のエラー処理をエミュレートする優れた方法です。

WRTは「サブクラスのメッセージプロパティが設定されていないように見える」、つまり、適切に構築されたエラーサブクラスを使用する場合はそうではありません。独自のErrorX Errorサブクラスを作成するには、「var MyError = "で始まるコードブロックをコピーして、1つの単語" MyError "を" ErrorX "に変更します。 (カスタムメソッドをサブクラスに追加する場合は、サンプルテキストに従ってください)。

JavaScriptエラーのサブクラス化の実際の重要な制限は、FireFoxのようなスタックトレースとインスタンス化の場所を追跡および報告するJavaScript実装またはデバッガーの場合、独自のErrorサブクラス実装の場所がインスタンス化ポイントとして記録されることです一方、直接エラーを使用した場合、「new Error(...)」を実行した場所になります)。 IEユーザーはおそらく気付かないでしょうが、FFのFire Bugのユーザーは、これらのエラーと一緒に報告された無用なファイル名と行番号の値を確認し、スタックトレースを要素#1にドリルダウンして見つける必要があります実際のインスタンス化の場所。

18
Blaine

このソリューションはどうですか?

以下を使用してカスタムエラーをスローする代わりに:

throw new MyError("Oops!");

Errorオブジェクト(デコレータのようなもの)をラップします。

throw new MyError(Error("Oops!"));

これにより、stack、fileName lineNumberなど、すべての属性が正しいことが確認されます。

あとは、属性をコピーするか、属性のゲッターを定義するだけです。ゲッター(IE9)を使用した例を次に示します。

function MyError(wrapped)
{
        this.wrapped = wrapped;
        this.wrapped.name = 'MyError';
}

function wrap(attr)
{
        Object.defineProperty(MyError.prototype, attr, {
                get: function()
                {
                        return this.wrapped[attr];
                }
        });
}

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

wrap('name');
wrap('message');
wrap('stack');
wrap('fileName');
wrap('lineNumber');
wrap('columnNumber');

MyError.prototype.toString = function()
{
        return this.wrapped.toString();
};
12
JoWie

私の解決策は、提供されている他の答えよりも簡単であり、欠点はありません。

ErrorプロトタイプチェーンとErrorのすべてのプロパティは、特定の知識がなくても保持されます。 Chrome、Firefox、Node、およびIE11でテストされています。

唯一の制限は、コールスタックの最上部の追加エントリです。しかし、それは簡単に無視されます。

2つのカスタムパラメータの例を次に示します

function CustomError(message, param1, param2) {
    var err = new Error(message);
    Object.setPrototypeOf(err, CustomError.prototype);

    err.param1 = param1;
    err.param2 = param2;

    return err;
}

CustomError.prototype = Object.create(
    Error.prototype,
    {name: {value: 'CustomError', enumerable: false}}
);

使用例:

try {
    throw new CustomError('Something Unexpected Happened!', 1234, 'neat');
} catch (ex) {
    console.log(ex.name); //CustomError
    console.log(ex.message); //Something Unexpected Happened!
    console.log(ex.param1); //1234
    console.log(ex.param2); //neat
    console.log(ex.stack); //stacktrace
    console.log(ex instanceof Error); //true
    console.log(ex instanceof CustomError); //true
}

setPrototypeOf:のpolyfilを必要とする環境の場合

Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
    obj.__proto__ = proto;
    return obj;
};
9
Ben

上記の例では、Error.applyError.callも)は何もしません(Firefox 3.6/Chrome 5)。私が使用する回避策は次のとおりです。

function MyError(message, fileName, lineNumber) {
    var err = new Error();

    if (err.stack) {
        // remove one stack level:
        if (typeof(Components) != 'undefined') {
            // Mozilla:
            this.stack = err.stack.substring(err.stack.indexOf('\n')+1);
        }
        else if (typeof(chrome) != 'undefined' || typeof(process) != 'undefined') {
            // Google Chrome/Node.js:
            this.stack = err.stack.replace(/\n[^\n]*/,'');
        }
        else {
            this.stack = err.stack;
        }
    }
    this.message    = message    === undefined ? err.message    : message;
    this.fileName   = fileName   === undefined ? err.fileName   : fileName;
    this.lineNumber = lineNumber === undefined ? err.lineNumber : lineNumber;
}

MyError.prototype = new Error();
MyError.prototype.constructor = MyError;
MyError.prototype.name = 'MyError';
8
panzi

一部の人が言っているように、ES6ではかなり簡単です。

class CustomError extends Error { }

それで、私は自分のアプリ(Angular、TypeScript)でそれを試しましたが、うまくいきませんでした。しばらくして、問題がTypeScriptから発生していることがわかりました:O

https://github.com/Microsoft/TypeScript/issues/13965 を参照してください

あなたがそうするなら、それは非常に不安です:

class CustomError extends Error {}
​

try {
  throw new CustomError()
} catch(e) {
  if (e instanceof CustomError) {
    console.log('Custom error');
  } else {
    console.log('Basic error');
  }
}

ノードで、または直接ブラウザに表示されます:Custom error

TypeScriptプレイグラウンドでプロジェクトのTypeScriptを使用して実行すると、Basic error...が表示されます。

解決策は以下を行うことです:

class CustomError extends Error {
  // we have to do the following because of: https://github.com/Microsoft/TypeScript/issues/13965
  // otherwise we cannot use instanceof later to catch a given type
  public __proto__: Error;

  constructor(message?: string) {
    const trueProto = new.target.prototype;
    super(message);

    this.__proto__ = trueProto;
  }
}
7
maxime1992

私の2セント:

なぜ別の答えですか?

a)Error.stackプロパティにアクセスすると(一部の回答のように)、パフォーマンスが大幅に低下するため。

b)1行しかないため。

c) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error のソリューションはスタック情報を保持していないようです。

//MyError class constructor
function MyError(msg){
    this.__proto__.__proto__ = Error.apply(null, arguments);
};

使用例

http://jsfiddle.net/luciotato/xXyeB/

それは何をするためのものか?

this.__proto__.__proto__MyError.prototype.__proto__であるため、MyErrorの__proto__ FOR ALL INSTANCESを特定の新しく作成されたエラーに設定しています。 MyErrorクラスのプロパティとメソッドを保持し、新しいErrorプロパティ(.stackを含む)を__proto__チェーンに配置します。

明らかな問題:

有用なスタック情報を持つMyErrorのインスタンスを複数持つことはできません。

this.__proto__.__proto__=の機能を完全に理解していない場合は、このソリューションを使用しないでください。

3
Lucio M. Tato

他の人がすでに述べたことに追加したいだけです。

カスタムエラークラスがスタックトレースに適切に表示されるようにするには、カスタムエラークラスのプロトタイプのnameプロパティをカスタムエラークラスのnameプロパティに設定する必要があります。これは私が意味することです:

CustomError.prototype = Error.prototype;
CustomError.prototype.name = 'CustomError';

したがって、完全な例は次のようになります。

    var CustomError = function(message) {
        var err = new Error(message);
        err.name = 'CustomError';
        this.name = err.name;
        this.message = err.message;
        //check if there is a stack property supported in browser
        if (err.stack) {
            this.stack = err.stack;
        }
        //we should define how our toString function works as this will be used internally
        //by the browser's stack trace generation function
        this.toString = function() {
           return this.name + ': ' + this.message;
        };
    };
    CustomError.prototype = new Error();
    CustomError.prototype.name = 'CustomError';

すべてが完了したら、新しい例外をスローし、次のようになります(chrome devツールで遅延試行しました):

CustomError: Stuff Happened. GASP!
    at Error.CustomError (<anonymous>:3:19)
    at <anonymous>:2:7
    at Object.InjectedScript._evaluateOn (<anonymous>:603:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:562:52)
    at Object.InjectedScript.evaluate (<anonymous>:481:21)
3
Gautham C.

Nodeでは、他の人が言ったように、簡単です。

class DumbError extends Error {
    constructor(foo = 'bar', ...params) {
        super(...params);

        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, DumbError);
        }

        this.name = 'DumbError';

        this.foo = foo;
        this.date = new Date();
    }
}

try {
    let x = 3;
    if (x < 10) {
        throw new DumbError();
    }
} catch (error) {
    console.log(error);
}
2
Muhammad Umer

JavaScriptの例外はサブクラス化が難しいため、サブクラス化はしません。新しいExceptionクラスを作成し、その内部でエラーを使用します。 Error.nameプロパティを変更して、コンソール上のカスタム例外のように表示します。

var InvalidInputError = function(message) {
    var error = new Error(message);
    error.name = 'InvalidInputError';
    return error;
};

上記の新しい例外は、通常のエラーのようにスローされ、期待どおりに動作します。たとえば、次のとおりです。

throw new InvalidInputError("Input must be a string");
// Output: Uncaught InvalidInputError: Input must be a string 

警告:スタックトレースは完全ではありません。新しいエラーが作成された場所であり、投げられた場所ではありません。これはChromeでは大した問題ではありません。コンソールで直接完全なスタックトレースを提供するためです。しかし、たとえばFirefoxではより問題があります。

2
Jonathan Benn

Mohsenの答えで指摘したように、ES6ではクラスを使用してエラーを拡張することが可能です。はるかに簡単で、その動作はネイティブエラーとより一貫しています...しかし、残念ながら、ES6以前のブラウザをサポートする必要がある場合、ブラウザでこれを使用するのは簡単なことではありません。それがどのように実装されるかについてのいくつかの注意については以下を参照してください。しかし、当面は、他の回答からの最良の提案のいくつかを組み込む比較的単純なアプローチをお勧めします。

function CustomError(message) {
    //This is for future compatibility with the ES6 version, which
    //would display a similar message if invoked without the
    //`new` operator.
    if (!(this instanceof CustomError)) {
        throw new TypeError("Constructor 'CustomError' cannot be invoked without 'new'");
    }
    this.message = message;

    //Stack trace in V8
    if (Error.captureStackTrace) {
       Error.captureStackTrace(this, CustomError);
    }
    else this.stack = (new Error).stack;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.name = 'CustomError';

ES6では、次のように簡単です。

class CustomError extends Error {}

...また、try {eval('class X{}')を使用してES6クラスのサポートを検出できますが、古いブラウザーでロードされたスクリプトにES6バージョンを含めようとすると、構文エラーが発生します。そのため、すべてのブラウザーをサポートする唯一の方法は、ES6をサポートするブラウザー用に個別のスクリプトを動的に(たとえば、AJAXまたはeval()経由で)ロードすることです。さらに複雑なのは、eval()がすべての環境でサポートされていないことです(コンテンツセキュリティポリシーにより)。これはプロジェクトの考慮事項である場合とそうでない場合があります。

したがって、現時点では、上記の最初のアプローチ、または単純にErrorを直接使用して、拡張を試みずに、ES6以外のブラウザーをサポートする必要があるコードに対して実際に実行できる最善の方法のようです。

一部の人々が検討したいもう1つのアプローチがあります。それは、カスタムエラータイプのインスタンスであるが、コンソールのネイティブエラーのように見えて動作するエラーオブジェクトを作成するためにObject.setPrototypeOf()を使用することです(おかげで- ベンの答え 推奨事項)。そのアプローチの私の見解は次のとおりです。 https://Gist.github.com/mbrowne/fe45db61cea7858d11be933a998926a8 。しかし、いつかES6を使用できるようになることを考えると、個人的には、このアプローチの複雑さがそれだけの価値があるかどうかはわかりません。

2
Matt Browne

これを行う方法は、コンストラクターから適用の結果を返すことと、通常の複雑なjavascriptyの方法でプロトタイプを設定することです。

function MyError() {
    var tmp = Error.apply(this, arguments);
    tmp.name = this.name = 'MyError'

    this.stack = tmp.stack
    this.message = tmp.message

    return this
}
    var IntermediateInheritor = function() {}
        IntermediateInheritor.prototype = Error.prototype;
    MyError.prototype = new IntermediateInheritor()

var myError = new MyError("message");
console.log("The message is: '"+myError.message+"'") // The message is: 'message'
console.log(myError instanceof Error)                // true
console.log(myError instanceof MyError)              // true
console.log(myError.toString())                      // MyError: message
console.log(myError.stack)                           // MyError: message \n 
                                                     // <stack trace ...>

この時点でそれを行うこの方法の唯一の問題(少し繰り返しました)は

  • stackおよびmessage以外のプロパティは、MyErrorおよび
  • スタックトレースには、実際には必要のない追加の行があります。

最初の問題は、この回答のトリックを使用して、エラーのすべての列挙不可能なプロパティを反復処理することで修正できます。 オブジェクトの列挙不可能な継承プロパティ名を取得することは可能ですか? ie <9ではサポートされていません。 2番目の問題は、スタックトレースでその行を削除することで解決できますが、それを安全に行う方法がわかりません(e.stack.toString()の2行目を削除するだけですか??)。

1
B T

カスタムエラーデコレータ

これは George Baileyの答え に基づいていますが、元のアイデアを拡張および単純化します。 CoffeeScriptで記述されていますが、JavaScriptに簡単に変換できます。アイデアは、ベイリーのカスタムエラーをラップするデコレーターで拡張し、新しいカスタムエラーを簡単に作成できるようにすることです。

注:これはV8でのみ機能します。他の環境ではError.captureStackTraceのサポートはありません。

定義する

デコレータは、エラータイプの名前を受け取り、エラーメッセージを受け取り、エラー名を囲む関数を返します。

CoreError = (@message) ->

    @constructor.prototype.__proto__ = Error.prototype
    Error.captureStackTrace @, @constructor
    @name = @constructor.name

BaseError = (type) ->

    (message) -> new CoreError "#{ type }Error: #{ message }"

つかいます

これで、新しいエラータイプを簡単に作成できます。

StorageError   = BaseError "Storage"
SignatureError = BaseError "Signature"

楽しみのために、引数が多すぎる場合にSignatureErrorを呼び出す関数を定義できるようになりました。

f = -> throw SignatureError "too many args" if arguments.length

これはかなりよくテストされており、V8で完全に動作し、トレースバック、位置などを維持しているようです。

注:カスタムエラーを作成する場合、newの使用はオプションです。

0
Carl Smith

スニペットはすべてを示しています。

function add(x, y) {
      if (x && y) {
        return x + y;
      } else {
        /**
         * 
         * the error thrown will be instanceof Error class and InvalidArgsError also
         */
        throw new InvalidArgsError();
        // throw new Invalid_Args_Error(); 
      }
    }

    // Declare custom error using using Class
    class Invalid_Args_Error extends Error {
      constructor() {
        super("Invalid arguments");
        Error.captureStackTrace(this);
      }
    }

    // Declare custom error using Function
    function InvalidArgsError(message) {
      this.message = `Invalid arguments`;
      Error.captureStackTrace(this);
    }
    // does the same magic as extends keyword
    Object.setPrototypeOf(InvalidArgsError.prototype, Error.prototype);

    try{
      add(2)
    }catch(e){
      // true
      if(e instanceof Error){
        console.log(e)
      }
      // true
      if(e instanceof InvalidArgsError){
        console.log(e)
      }
    }
0
Amarpreet Singh

私は一歩後退して、なぜあなたがそれをしたいのかを考えますか?重要なのは、異なるエラーに異なる方法で対処することだと思います。

たとえば、Pythonでは、catchステートメントをMyValidationErrorのみをキャッチするように制限できます。また、javascriptでも同様のことができるようにしたい場合があります。

catch (MyValidationError e) {
    ....
}

Javascriptでこれを行うことはできません。 catchブロックは1つだけになります。エラーのifステートメントを使用して、そのタイプを判別することになっています。

catch(e) { if(isMyValidationError(e)) { ... } else { // maybe rethrow? throw e; } }

代わりに、型、メッセージ、その他の適切なプロパティを持つ生のオブジェクトをスローすると思います。

throw { type: "validation", message: "Invalid timestamp" }

そして、エラーをキャッチすると:

catch(e) {
    if(e.type === "validation") {
         // handle error
    }
    // re-throw, or whatever else
}
0
hasen