JavaScriptでカスタムエラーを作成するにはどうすればよいですか?


215

何らかの理由で、次のスニペットではコンストラクター委任が機能しないようです。

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コンストラクターへのingに問題がありますか?


変更後、nie instanceof NotImplementedErrorアサーションは機能しますか?これが機能するためには、NotImplementedError.prototype.constructorを明示的に定義する必要があると思いました。
jayarjo

次回は、問題のデモンストレーションに不要な無関係のコードをすべて削除してください。また、wtcはjs.jarですか?問題を再現するために必要ですか?
BT

2
この質問を編集して、10分ではなく10秒で理解できるようにしました
BT

エラータイプから適切に継承する継承/クラスライブラリを作成しました:github.com/fresheneesz/proto
BT

1
上位の回答のいくつかについてはjsfiddle
2015

回答:


194

コードを更新して、プロトタイプを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()ニコラス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

これにより、私が遭遇した「問題」は、エラーのスタックプロパティが、発生した場所でnew Error()はなく、作成された行番号であることが確認されましthrow eた。ただし、NotImplementedError.prototype.name = "NotImplementedError"Errorオブジェクトに影響を与える行の副作用がある場合よりも良い場合があります。

また、で明示的にNotImplementedError2設定しない.nameと、「エラー」に等しいことに注意してください。ただし、コメントで述べたように、そのバージョンではプロトタイプnew Error()がに設定されているため、設定NotImplementedError2.prototype.name = "NotImplementedError2"して問題ありません。


45
ベストアンサーですが、Error.prototype直接服用することはおそらく悪い形です。後でNotImplementedError.prototype.toStringオブジェクトを追加する場合は、オブジェクトのエイリアスを設定Error.prototype.toStringしますNotImplementedError.prototype = new Error()
補助

4
私はこれらすべてのプロトタイプのものでまだ少し迷っています。あなたの例でなぜあなたがthis.nameに名前を割り当て、NotImplementedError.prototype.nameではないのですか?答えてください、それは私の理解にとって非常に重要です:)
jayarjo

27
code.google.com/p/chromium/issues/detail?id=228909に よると、形式subclass.prototype = new Error()不適切です。subclass.prototype = Object.create(superclass.prototype)代わりに使用することになっています。スタックトレースの問題も修正されることを期待しています。
ギリ2013

8
意味のあるスタックトレースを取得するための簡単なトリックは、コンストラクターでエラーを生成し、そのスタックを保存することです。それは適切なコールスタック+コンストラクター用の1行を提供します(適切なthis.stack = new Error().stack;
見返りです

6
-1; これは間違っています。実行すると、NotImplementedError.prototype = Error.prototype;作成しませんinstanceof御馳走をNotImplementedError通り、サブクラスError落札、instanceof正確に同じクラスとして扱います。上記のコードをコンソールに貼り付けて試してnew Error() instanceof NotImplementedErrorみるとtrue、明らかに間違っています。
Mark Amery 2016年

87

上記の答えはすべてひどいひどいです-本当に。107アップの方でも!本当の答えはここの男です:

Errorオブジェクトから継承-メッセージプロパティはどこにありますか?

TL; DR:

A. message設定されていないのErrorは、新しいErrorオブジェクトを返し、何の操作もしない関数だからthisです。

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

function MyError() {
    var temp = Error.apply(this, arguments);
    temp.name = this.name = 'MyError';
    this.message = temp.message;
    if(Object.defineProperty) {
        // getter for more optimizy goodness
        /*this.stack = */Object.defineProperty(this, 'stack', { 
            get: function() {
                return temp.stack
            },
            configurable: true // so you can change it if you want
        })
    } else {
        this.stack = temp.stack
    }
}
//inherit prototype using ECMAScript 5 (IE 9+)
MyError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: MyError,
        writable: true,
        configurable: true
    }
});

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 ...>


 
//for EMCAScript 4 or ealier (IE 8 or ealier), inherit prototype this way instead of above code:
/*
var IntermediateInheritor = function() {};
IntermediateInheritor.prototype = Error.prototype;
MyError.prototype = new IntermediateInheritor();
*/

and tmpだけstackを明示的に設定するのではなく、Errorの列挙できないすべてのプロパティを列挙して設定するために、いくつかのトリックを行うことができますがmessage、ie <9ではそのトリックはサポートされていません。


2
このソリューションは、既存のエラーを使用してカスタムエラーをインスタンス化する場合にも機能します。サードパーティのライブラリを使用していて、既存のエラーを独自のカスタムタイプでラップしたい場合、他のメソッドは正しく機能しません。参考までに、既存のエラーを渡すことで、バニラエラーをインスタンス化できます。
カイルミューラー14

1
return thisコンストラクタには入れないでください。
OnurYıldırım2015年

13
このアプローチを少し簡略化して改善しました:jsbin.com/rolojuhuya/1/edit?js,console
Matt Kantor

3
@MattKantorはおそらくそれを答えにしますか?私はあなたが一番好きだと思います。
mpoisot 2015

2
代わりにtemp.name = this.name = 'MyError'、あなたがすることができますtemp.name = this.name = this.constructor.name。そうすれば、サブクラスでMyErrorも機能します。
Jo Liss、2015年

45

ES2015では、これを使用classしてこれをきれいに行うことができます:

class NotImplemented extends Error {
  constructor(message = "", ...args) {
    super(message, ...args);
    this.message = message + " has not yet been implemented.";
  }
}

これはグローバルErrorプロトタイプを変更せず、、、およびその他の属性をカスタマイズしてmessagenameスタックを適切にキャプチャできます。また、かなり読みやすいです。

もちろん、babel古いブラウザでコードを実行する場合のようなツールを使用する必要があるかもしれません。


23

カスタムエラーを作成してスタックトレース取得する方法に興味がある場合:

function CustomError(message) {
  this.name = 'CustomError';
  this.message = message || '';
  var error = new Error(this.message);
  error.name = this.name;
  this.stack = error.stack;
}
CustomError.prototype = Object.create(Error.prototype);

try {
  throw new CustomError('foobar');
}
catch (e) {
  console.log('name:', e.name);
  console.log('message:', e.message);
  console.log('stack:', e.stack);
}

7

標準のこのセクションでは、Error.apply呼び出しがオブジェクトを初期化しない理由を説明している場合があります。

15.11.1関数として呼び出されるエラーコンストラクタ

Errorがコンストラクタではなく関数として呼び出されると、新しいErrorオブジェクトが作成および初期化されます。したがって、関数呼び出しError(...)は、同じ引数を持つオブジェクト作成式new Error(...)と同等です。

この場合、Error関数はおそらくコンストラクタとして呼び出されていないと判断するため、thisオブジェクトを初期化するのではなく、新しいErrorインスタンスを返します。

次のコードを使用したテストは、これが実際に何が起こっているかを示しているようです。

function NotImplementedError() { 
   var returned = Error.apply(this, arguments);
   console.log("returned.message = '" + returned.message + "'");
   console.log("this.message = '" + this.message + "'");
}
NotImplementedError.prototype = new Error();

var nie = new NotImplementedError("some message");

これを実行すると、次の出力が生成されます。

returned.message = 'some message'
this.message = ''

これをカスタムエラークラスでどのようにシミュレートできますか?たとえば、カスタムエラークラスは、インスタンスを作成する関数とコンストラクターの両方としてどのように使用できますか?
Lea Hayes

いいえ、これは正しくありません。新しいErrorインスタンスを返した場合、彼のmsgプロパティは機能します。
BT

@BT新しいインスタンスのmsgプロパティはthis、inのmsgプロパティにどのように影響しError.apply(this, arguments);ますか?ここでのErrorの呼び出しは、新しいオブジェクトを構築していることを示しています。このオブジェクトは破棄されます。に割り当てられてnieいる、すでに構築されているオブジェクトを初期化しません。
デイブ

@BT私が言おうとしていたことがより明確になるようにいくつかのサンプルコードを追加しました。
デイブ

@Dave私はここで目的を誤解したかもしれませんが、NotImplementedError実装はreturned変数を返すべきではありませんか?
2013

7
function InvalidValueError(value, type) {
    this.message = "Expected `" + type.name + "`: " + value;
    var error = new Error(this.message);
    this.stack = error.stack;
}
InvalidValueError.prototype = new Error();
InvalidValueError.prototype.name = InvalidValueError.name;
InvalidValueError.prototype.constructor = InvalidValueError;

3
これがここでの最良の答えです。これは簡潔であり、この方法で作成された例外はすべての状況で正しく動作します。また、重要なアプリケーションで非常に重要なスタックトレースを保持します。「prototype = new Error()」を「prototype = Object.create(Error.prototype)」に置き換えるだけです。Node.jsには、これを行う小さなライブラリがあります。npmjs.com
Lukasz

6

これと同様の問題がありました。私のエラーのニーズがあることをinstanceof両方ErrorNotImplemented、それはまた、コンソールのコヒーレントバックトレースを生成する必要があります。

私の解決策:

var NotImplemented = (function() {
  var NotImplemented, err;
  NotImplemented = (function() {
    function NotImplemented(message) {
      var err;
      err = new Error(message);
      err.name = "NotImplemented";
      this.message = err.message;
      if (err.stack) this.stack = err.stack;
    }
    return NotImplemented;
  })();
  err = new Error();
  err.name = "NotImplemented";
  NotImplemented.prototype = err;

  return NotImplemented;
}).call(this);

// TEST:
console.log("instanceof Error: " + (new NotImplemented() instanceof Error));
console.log("instanceof NotImplemented: " + (new NotImplemented() instanceofNotImplemented));
console.log("message: "+(new NotImplemented('I was too busy').message));
throw new NotImplemented("just didn't feel like it");

node.jsで実行した結果:

instanceof Error: true
instanceof NotImplemented: true
message: I was too busy

/private/tmp/t.js:24
throw new NotImplemented("just didn't feel like it");
      ^
NotImplemented: just didn't feel like it
    at Error.NotImplemented (/Users/colin/projects/gems/jax/t.js:6:13)
    at Object.<anonymous> (/Users/colin/projects/gems/jax/t.js:24:7)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:487:10)
    at process.startup.processNextTick.process._tickCallback (node.js:244:9)

エラーは私の3つの基準すべてに合格し、stackプロパティは非標準ですが、ほとんどの新しいブラウザーサポートされており、私の場合は許容可能です。


5

Joyentによると、パフォーマンスに悪影響を与えるため、スタックプロパティ(ここに記載されている多くの回答に記載されています)をいじらないでください。彼らが言うことはここにあります:

スタック:一般に、これを台無しにしないでください。それを増大させないでください。V8は、誰かが実際にプロパティを読み取った場合にのみそれを計算します。これにより、処理可能なエラーのパフォーマンスが劇的に向上します。プロパティを拡張するためだけにプロパティを読んだ場合、呼び出し元がスタックを必要としていない場合でも、最終的にコストを支払うことになります。

元のエラーラップするという彼らのアイデアに触れたいと思います。これは、スタックを渡すための優れた代替品です。

上記のことを考慮して、カスタムエラーを作成する方法を次に示します。

es5バージョン:

function RError(options) {
    options = options || {}; // eslint-disable-line no-param-reassign
    this.name = options.name;
    this.message = options.message;
    this.cause = options.cause;

    // capture stack (this property is supposed to be treated as private)
    this._err = new Error();

    // create an iterable chain
    this.chain = this.cause ? [this].concat(this.cause.chain) : [this];
}
RError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: RError,
        writable: true,
        configurable: true
    }
});

Object.defineProperty(RError.prototype, 'stack', {
    get: function stack() {
        return this.name + ': ' + this.message + '\n' + this._err.stack.split('\n').slice(2).join('\n');
    }
});

Object.defineProperty(RError.prototype, 'why', {
    get: function why() {
        var _why = this.name + ': ' + this.message;
        for (var i = 1; i < this.chain.length; i++) {
            var e = this.chain[i];
            _why += ' <- ' + e.name + ': ' + e.message;
        }
        return _why;
    }
});

// usage

function fail() {
    throw new RError({
        name: 'BAR',
        message: 'I messed up.'
    });
}

function failFurther() {
    try {
        fail();
    } catch (err) {
        throw new RError({
            name: 'FOO',
            message: 'Something went wrong.',
            cause: err
        });
    }
}

try {
    failFurther();
} catch (err) {
    console.error(err.why);
    console.error(err.stack);
    console.error(err.cause.stack);
}

es6バージョン:

class RError extends Error {
    constructor({name, message, cause}) {
        super();
        this.name = name;
        this.message = message;
        this.cause = cause;
    }
    [Symbol.iterator]() {
        let current = this;
        let done = false;
        const iterator = {
            next() {
                const val = current;
                if (done) {
                    return { value: val, done: true };
                }
                current = current.cause;
                if (!val.cause) {
                    done = true;
                }
                return { value: val, done: false };
            }
        };
        return iterator;
    }
    get why() {
        let _why = '';
        for (const e of this) {
            _why += `${_why.length ? ' <- ' : ''}${e.name}: ${e.message}`;
        }
        return _why;
    }
}

// usage

function fail() {
    throw new RError({
        name: 'BAR',
        message: 'I messed up.'
    });
}

function failFurther() {
    try {
        fail();
    } catch (err) {
        throw new RError({
            name: 'FOO',
            message: 'Something went wrong.',
            cause: err
        });
    }
}

try {
    failFurther();
} catch (err) {
    console.error(err.why);
    console.error(err.stack);
    console.error(err.cause.stack);
}

私は自分のソリューションをモジュールに入れました。ここにそれがあります:https : //www.npmjs.com/package/rerror


3

私はそれをこのようにするのが好きです:

  • 名前を使用してtoString()がスローするようにする"{code}: {message}"
  • 同じものをスーパーに返すので、スタックトレースで同じように見えます
  • error.codeたとえば、ローカライズしたいメッセージをチェックするよりも、コードをチェック/解析する方がコードでコードを添付する方がよい
  • error.message代わりにメッセージを添付error.toString()

class AppException extends Error {
  constructor(code, message) {
    const fullMsg = message ? `${code}: ${message}` : code;
    super(fullMsg);
    this.name = code;
    this.code = code;
    this.message = fullMsg;
  }
  
  toString() {
    return this.message;
  }
}

// Just a code
try {
  throw new AppException('FORBIDDEN');
} catch(e) {
  console.error(e);
  console.error(e.toString());
  console.log(e.code === 'FORBIDDEN');
}

// A code and a message
try {
  throw new AppException('FORBIDDEN', 'You don\'t have access to this page');
} catch(e) {
  console.error(e);
  console.error(e.toString());
  console.log(e.code === 'FORBIDDEN');
}


2

私はこのようなものを実装する必要があり、自分のエラー実装でスタックが失われていることがわかりました。私がしなければならなかったことは、ダミーエラーを作成し、そこからスタックを取得することでした:

My.Error = function (message, innerException) {
    var err = new Error();
    this.stack = err.stack; // IMPORTANT!
    this.name = "Error";
    this.message = message;
    this.innerException = innerException;
}
My.Error.prototype = new Error();
My.Error.prototype.constructor = My.Error;
My.Error.prototype.toString = function (includeStackTrace) {
    var msg = this.message;
    var e = this.innerException;
    while (e) {
        msg += " The details are:\n" + e.message;
        e = e.innerException;
    }
    if (includeStackTrace) {
        msg += "\n\nStack Trace:\n\n" + this.stack;
    }
    return msg;
}

これはメッセージを設定しません
BT

2

コンストラクタパターンを使用して、新しいエラーオブジェクトを作成しました。インスタンスなどのプロトタイプチェーンを定義しましたError。MDN エラーコンストラクタリファレンスをご覧ください。

このスニペットは、この要点で確認できます。

実装

// Creates user-defined exceptions
var CustomError = (function() {
  'use strict';

  //constructor
  function CustomError() {
    //enforces 'new' instance
    if (!(this instanceof CustomError)) {
      return new CustomError(arguments);
    }
    var error,
      //handles the arguments object when is passed by enforcing a 'new' instance
      args = Array.apply(null, typeof arguments[0] === 'object' ? arguments[0] : arguments),
      message = args.shift() || 'An exception has occurred';

    //builds the message with multiple arguments
    if (~message.indexOf('}')) {
      args.forEach(function(arg, i) {
        message = message.replace(RegExp('\\{' + i + '}', 'g'), arg);
      });
    }

    //gets the exception stack
    error = new Error(message);
    //access to CustomError.prototype.name
    error.name = this.name;

    //set the properties of the instance
    //in order to resemble an Error instance
    Object.defineProperties(this, {
      stack: {
        enumerable: false,
        get: function() { return error.stack; }
      },
      message: {
        enumerable: false,
        value: message
      }
    });
  }

  // Creates the prototype and prevents the direct reference to Error.prototype;
  // Not used new Error() here because an exception would be raised here,
  // but we need to raise the exception when CustomError instance is created.
  CustomError.prototype = Object.create(Error.prototype, {
    //fixes the link to the constructor (ES5)
    constructor: setDescriptor(CustomError),
    name: setDescriptor('JSU Error')
  });

  function setDescriptor(value) {
    return {
      configurable: false,
      enumerable: false,
      writable: false,
      value: value
    };
  }

  //returns the constructor
  return CustomError;
}());

使用法

CustomErrorコンストラクターは、メッセージを作成するために多くの引数を受け取ることができます。

var err1 = new CustomError("The url of file is required"),
    err2 = new CustomError("Invalid Date: {0}", +"date"),
    err3 = new CustomError("The length must be greater than {0}", 4),
    err4 = new CustomError("Properties .{0} and .{1} don't exist", "p1", "p2");

throw err4;

そして、これはカスタムエラーがどのように見えるかです:

カスタムエラープロトタイプチェーン


反対票を投じた人、あなたは議論がありますか、反対する理由はありますか?または単にコードの意図を理解していません。
jherax

気付かないうちにこのページを閲覧しているときに(おそらく携帯電話から閲覧している場合)、誤って反対投票ボタンをクリックしたのに気づきました。私は今日、自分の履歴を閲覧しているときに気づきました。意図的なものではありませんが、猶予期間中のため、元に戻すことはできません。有益な回答を提供しましたが、それに値するものではありません。編集した場合、私は喜んで反対票を取り消します。申し訳ありません。
jschr 2016

1

コンストラクターはファクトリーメソッドのようなものであり、必要なものを返す必要があります。追加のメソッド/プロパティが必要な場合は、返す前にそれらをオブジェクトに追加できます。

function NotImplementedError(message) { return new Error("Not implemented", message); }

x = new NotImplementedError();

なぜこれを行う必要があるのか​​はわかりませんが。なぜ使用しないのnew Error...ですか?カスタム例外は、JavaScript(またはおそらく型付けされていない言語)に実際には多くを追加しません。


2
単一のcatchブロックしか指定できないため、JavaScriptでError-type-hierarchyまたはobject-valueをオンにする必要があります。あなたのソリューションでは、(x instanceof NotImplementedError)はfalseですが、私の場合は許容できません。
cdleary 2009

1

これはCesium DeveloperErrorにうまく実装されています:

それは単純化された形で:

var NotImplementedError = function(message) {
    this.name = 'NotImplementedError';
    this.message = message;
    this.stack = (new Error()).stack;
}

// Later on...

throw new NotImplementedError();

これは問題なく機能するエラーコンストラクターの追加の行がスタックに含まれることを除いて、うまく機能します。
SystemParadox 2015

また、error instanceof Errorテストに合格しないため、役立ちます。
ローレン

1

これは私の実装です:

class HttpError extends Error {
  constructor(message, code = null, status = null, stack = null, name = null) {
    super();
    this.message = message;
    this.status = 500;

    this.name = name || this.constructor.name;
    this.code = code || `E_${this.name.toUpperCase()}`;
    this.stack = stack || null;
  }

  static fromObject(error) {
    if (error instanceof HttpError) {
      return error;
    }
    else {
      const { message, code, status, stack } = error;
      return new ServerError(message, code, status, stack, error.constructor.name);
    }
  }

  expose() {
    if (this instanceof ClientError) {
      return { ...this };
    }
    else {
      return {
        name: this.name,
        code: this.code,
        status: this.status,
      }
    }
  }
}

class ServerError extends HttpError {}

class ClientError extends HttpError { }

class IncorrectCredentials extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 400;
  }
}

class ResourceNotFound extends ClientError {
  constructor(...args) {
    super(...args);
    this.status = 404;
  }
}

使用例#1:

app.use((req, res, next) => {
  try {
    invalidFunction();
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

使用例#2:

router.post('/api/auth', async (req, res) => {
  try {
    const isLogged = await User.logIn(req.body.username, req.body.password);

    if (!isLogged) {
      throw new IncorrectCredentials('Incorrect username or password');
    }
    else {
      return res.status(200).send({
        token,
      });
    }
  }
  catch (err) {
    const error = HttpError.fromObject(err);
    return res.status(error.status).send(error.expose());
  }
});

0

を使用できないという犠牲を払ってinstanceof、以下は元のスタックトレースを保持し、非標準のトリックを使用しません。

// the function itself
var fixError = function(err, name) {
    err.name = name;
    return err;
}

// using the function
try {
    throw fixError(new Error('custom error message'), 'CustomError');
} catch (e) {
    if (e.name == 'CustomError')
        console.log('Wee! Custom Error! Msg:', e.message);
    else
        throw e; // unhandled. let it propagate upwards the call stack
}

instanceofを使用できるようにするためにここでしなければならないことは、fixErrorだけでなく、新しいfixErrorをスローすることです
BT

@BT:fixError上記の関数ではありません。new呼び出し時にaを追加すると、破棄されるオブジェクトが作成されます。
TJクラウダー

ああ、私は「fixErrorのinstanceof」を使用して意味を推測-ない仕事..私はそれが悪いことだと思うだろう「エラーのinstanceof」もちろん、その後の...
BT

0

別の代替方法は、すべての環境で機能するわけではありません。少なくとも、nodejs 0.8で機能することを保証します。

function myError(msg){ 
      var e = new Error(msg); 
      _this = this; 
      _this.__proto__.__proto__ = e;
}

0

Node / Chromeを使用している場合。次のスニペットは、次の要件を満たす拡張機能を取得します。

  • err instanceof Error
  • err instanceof CustomErrorType
  • console.log()は[CustomErrorType]メッセージ付きで作成されると戻ります
  • console.log()が返す [CustomErrorType: message]メッセージなしで作成するとれる
  • throw / stackは、エラーが作成された時点の情報を提供します。
  • Node.JS、およびChromeで最適に動作します。
  • Chrome、Safari、Firefox、IE 8以降でinstanceofチェックに合格しますが、Chrome / Safariの外部では有効なスタックがありません。Chromeでデバッグできるので問題ありませんが、特定のエラータイプを必要とするコードは、引き続きクロスブラウザーで機能します。Nodeだけが必要な場合は、ifステートメントを簡単に削除できます

スニペット

var CustomErrorType = function(message) {
    if (Object.defineProperty) {
        Object.defineProperty(this, "message", {
            value : message || "",
            enumerable : false
        });
    } else {
        this.message = message;
    }

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

CustomErrorType.prototype = new Error();
CustomErrorType.prototype.name = "CustomErrorType";

使用法

var err = new CustomErrorType("foo");

出力

var err = new CustomErrorType("foo");
console.log(err);
console.log(err.stack);

[CustomErrorType: foo]
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

/errorTest.js:30
        throw err;
              ^
CustomErrorType: foo
    at Object.<anonymous> (/errorTest.js:27:12)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

0

以下は、Mozillaの公式ドキュメントErrorから取得した私にとってはうまくいきました

function NotImplementedError(message) {
    var instance = new Error(message);
    instance.name = 'NotImplementedError';

    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    if (Error.captureStackTrace) {
        Error.captureStackTrace(instance, NotImplementedError);
    }
    return instance;
}

NotImplementedError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: Error,
        enumerable: false,
        writable: true,
        configurable: true
    }
});

-1

ユーザー定義のエラータイプのインスタンスごとに新しいプロトタイプオブジェクトを試してください。これにより、instanceofチェックが通常どおりに動作し、タイプとメッセージがFirefoxおよびV8(Chome、nodejs)で正しく報告されます。

function NotImplementedError(message){
    if(NotImplementedError.innercall===undefined){
        NotImplementedError.innercall = true;
        NotImplementedError.prototype = new Error(message);
        NotImplementedError.prototype.name = "NotImplementedError";
        NotImplementedError.prototype.constructor = NotImplementedError;

        return new NotImplementedError(message);
    }
    delete NotImplementedError.innercall;
}

追加のエントリは、それ以外の場合は正しいスタックの前にあることに注意してください。


動作しません。試してみてください:var a = new NotImplementedError('a'), b = new NotImplementedError('b');。今a instanceof NotImplementedError == falseb instanceof NotImplementedError == true
jjrv

-1

これが最も速い方法です。

    let thisVar = false

    if (thisVar === false) {
            throw new Error("thisVar is false. It should be true.")
    }

-3

より簡単な方法。オブジェクトにErrorオブジェクトを継承させることができます。例:

function NotImplementError(message)
{
    this.message = message;
    Error.call();
    Error.call(message);
} 

Errorクラスのコンストラクターを呼び出す関数call()を使用しているので、基本的には他のオブジェクト指向言語でクラス継承を実装するのと同じです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.