Aus irgendeinem Grund sieht es so aus, als ob die Konstruktordelegierung im folgenden Snippet nicht funktioniert:
function NotImplementedError() {
Error.apply(this, arguments);
}
NotImplementedError.prototype = new Error();
var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")
Laufen dies gibt The message is: ''
. Irgendwelche Ideen, warum oder ob es einen besseren Weg gibt, eine neue Error
Unterklasse zu erstellen ? Gibt es ein Problem mit apply
dem nativen Error
Konstruktor, von dem ich nichts weiß?
javascript
exception
cdleary
quelle
quelle
Antworten:
Aktualisieren Sie Ihren Code, um Ihren Prototyp dem Error.prototype zuzuweisen, und die Instanz von und Ihre Asserts funktionieren.
Ich würde jedoch einfach Ihr eigenes Objekt werfen und nur die Namenseigenschaft überprüfen.
Bearbeiten Sie basierend auf Kommentaren
Nachdem ich mir die Kommentare angesehen und versucht hatte, mich daran zu erinnern, warum ich den Prototyp
Error.prototype
anstelle vonnew Error()
Nicholas Zakas in seinem Artikel zugewiesen hatte , erstellte ich eine jsFiddle mit dem folgenden Code:Die Konsolenausgabe war dies.
Dies bestätigt, dass das "Problem", auf das ich gestoßen bin, darin bestand, dass die Stapeleigenschaft des Fehlers die Zeilennummer
new Error()
war, in der sie erstellt wurde, und nicht, wo dasthrow e
aufgetreten ist. Dies kann jedoch besser sein, als den Nebeneffekt einerNotImplementedError.prototype.name = "NotImplementedError"
Linie zu haben, die das Fehlerobjekt beeinflusst.Beachten Sie auch, dass
NotImplementedError2
, wenn ich das nicht.name
explizit einstelle , es gleich "Fehler" ist. Wie in den Kommentaren erwähnt,new Error()
könnte ich jedoch festlegenNotImplementedError2.prototype.name = "NotImplementedError2"
und in Ordnung sein , da diese Version den Prototyp festlegt .quelle
Error.prototype
direkt zu nehmen ist wahrscheinlich eine schlechte Form. Wenn Sie später einNotImplementedError.prototype.toString
Objekt hinzufügen möchten, ist der Aliase jetzt AliaseError.prototype.toString
- besser zu tunNotImplementedError.prototype = new Error()
.subclass.prototype = new Error()
ist die Form schlecht. Sie solltensubclass.prototype = Object.create(superclass.prototype)
stattdessen verwenden. Ich hoffe, dass dadurch auch das Stack-Trace-Problem behoben werden kann.this.stack = new Error().stack;
NotImplementedError.prototype = Error.prototype;
machen sich nichtinstanceof
behandelnNotImplementedError
als Unterklasse vonError
, macht esinstanceof
behandelt sie als genau die gleiche Klasse. Wenn Sie den obigen Code in Ihre Konsole einfügen und versuchen, erhaltennew Error() instanceof NotImplementedError
Sietrue
, was eindeutig falsch ist.Alle oben genannten Antworten sind schrecklich schrecklich - wirklich. Sogar der mit 107 Ups! Die wirkliche Antwort ist hier Jungs:
Erben vom Fehlerobjekt - Wo befindet sich die Nachrichteneigenschaft?
TL; DR:
A. Der Grund dafür
message
ist nicht in der Reihe ist , dassError
eine Funktion, die ein neues Error - Objekt zurückgibt und nicht nicht manipulierenthis
in keiner Weise.B. Der Weg, dies richtig zu machen, besteht darin, das Ergebnis der Anwendung vom Konstruktor zurückzugeben und den Prototyp auf die übliche komplizierte Art und Weise zu setzen:
Sie könnten wahrscheinlich einige Tricks ausführen, um alle nicht aufzählbaren Eigenschaften des
tmp
Fehlers aufzulisten, um sie festzulegen, anstatt nur explizitstack
undmessage
festzulegen, aber der Trick wird in dh <9 nicht unterstütztquelle
return this
in einem Konstruktor.temp.name = this.name = 'MyError'
können Sie tuntemp.name = this.name = this.constructor.name
. Auf diese Weise funktioniert es auch für Unterklassen vonMyError
.In ES2015 können Sie
class
dies sauber machen:Dies schließt nicht global ändern
Error
Prototyp, können Sie anpassenmessage
,name
und andere Attribute und fängt richtig den Stapel. Es ist auch ziemlich lesbar.Natürlich müssen Sie möglicherweise ein Tool verwenden, z. B.
babel
wenn Ihr Code in älteren Browsern ausgeführt wird.quelle
Wenn jemand neugierig ist, wie ein benutzerdefinierter Fehler erstellt und der Stack-Trace abgerufen werden kann :
quelle
In diesem Abschnitt des Standards wird möglicherweise erläutert, warum der
Error.apply
Aufruf das Objekt nicht initialisiert:In diesem Fall stellt die
Error
Funktion wahrscheinlich fest, dass sie nicht als Konstruktor aufgerufen wird, und gibt daher eine neue Fehlerinstanz zurück, anstatt dasthis
Objekt zu initialisieren .Das Testen mit dem folgenden Code scheint zu zeigen, dass dies tatsächlich der Fall ist:
Die folgende Ausgabe wird generiert, wenn dies ausgeführt wird:
quelle
this
in ausError.apply(this, arguments);
? Ich sage, der Aufruf zum Fehler hier besteht darin, ein neues Objekt zu konstruieren, das weggeworfen wird. Das bereits erstellte Objekt, dem zugewiesen ist, wird nicht initialisiertnie
.NotImplementedError
Implementierung diereturned
Variable nicht zurückgeben?quelle
Ich hatte ein ähnliches Problem. Mein Fehler muss
instanceof
beidesError
undNotImplemented
ein kohärenter Backtrace in der Konsole sein.Meine Lösung:
Ergebnis der Ausführung mit node.js:
Der Fehler besteht alle drei meiner Kriterien und obwohl die
stack
Eigenschaft nicht dem Standard entspricht, wird sie in den meisten neueren Browsern unterstützt, was in meinem Fall akzeptabel ist.quelle
Joyent zufolge sollten Sie sich nicht mit der Stack-Eigenschaft herumschlagen (die ich in vielen hier gegebenen Antworten sehe), da dies sich negativ auf die Leistung auswirkt. Hier ist was sie sagen:
Ich mag und möchte ihre Idee erwähnen, den ursprünglichen Fehler zu verpacken, der ein guter Ersatz für die Weitergabe des Stapels ist.
So erstelle ich einen benutzerdefinierten Fehler unter Berücksichtigung der oben genannten Punkte:
es5 version:
es6 version:
Ich habe meine Lösung in ein Modul eingefügt, hier ist es: https://www.npmjs.com/package/rerror
quelle
Ich mache es gerne so:
"{code}: {message}"
error.code
da das Überprüfen / Parsen eines Codes im Code besser ist als das Überprüfen einer Nachricht, die Sie beispielsweise lokalisieren möchtenerror.message
Als Alternative zu Nachricht anhängenerror.toString()
quelle
Ich musste nur so etwas implementieren und stellte fest, dass der Stack in meiner eigenen Fehlerimplementierung verloren ging. Was ich tun musste, war einen Dummy-Fehler zu erstellen und den Stapel daraus abzurufen:
quelle
Ich habe das Konstruktormuster verwendet, um das neue Fehlerobjekt zu erstellen. Ich habe die Prototypkette wie eine
Error
Instanz definiert. Siehe die MDN- Fehlerkonstruktorreferenz .Sie können dieses Snippet in diesem Kern überprüfen .
IMPLEMENTIERUNG
VERWENDUNG
Der CustomError-Konstruktor kann viele Argumente zum Erstellen der Nachricht empfangen, z
Und so sieht der benutzerdefinierte Fehler aus:
quelle
Der Konstruktor muss wie eine Factory-Methode sein und das zurückgeben, was Sie möchten. Wenn Sie zusätzliche Methoden / Eigenschaften benötigen, können Sie diese dem Objekt hinzufügen, bevor Sie es zurückgeben.
Obwohl ich nicht sicher bin, warum Sie das tun müssen. Warum nicht einfach benutzen
new Error...
? Benutzerdefinierte Ausnahmen fügen in JavaScript (oder wahrscheinlich in einer nicht typisierten Sprache) nicht wirklich viel hinzu.quelle
Dies ist im Cäsium DeveloperError gut implementiert:
In seiner vereinfachten Form:
quelle
error instanceof Error
Test auch nicht, was hilfreich sein kann.Dies ist meine Implementierung:
Anwendungsbeispiel Nr. 1:
Anwendungsbeispiel Nr. 2:
quelle
Auf Kosten der
instanceof
Nichtverwendung wird im Folgenden die ursprüngliche Stapelverfolgung beibehalten und es werden keine nicht standardmäßigen Tricks verwendet.quelle
fixError
obigen Funktion. Wenn Sienew
beim Aufrufen ein hinzufügen, wird nur ein Objekt erstellt, das weggeworfen wird.Eine andere Alternative funktioniert möglicherweise nicht in allen Umgebungen. Zumindest versichert, dass sie in NodeJS 0.8 funktioniert. Dieser Ansatz verwendet eine nicht standardmäßige Methode zum Ändern der internen Proto-Requisite
quelle
Wenn Sie Node / Chrome verwenden. Mit dem folgenden Snippet erhalten Sie eine Erweiterung, die die folgenden Anforderungen erfüllt.
err instanceof Error
err instanceof CustomErrorType
[CustomErrorType]
wenn eine Nachricht erstellt wird[CustomErrorType: message]
wenn es ohne Nachricht erstellt wurdeif
Anweisungen einfach entfernen und loslegen .Snippet
Verwendung
Ausgabe
quelle
Folgendes funktionierte für mich aus der offiziellen Mozilla-Dokumentation Fehler .
quelle
Probieren Sie für jede Instanz des benutzerdefinierten Fehlertyps ein neues Prototypobjekt aus. Damit können sich
instanceof
Überprüfungen wie gewohnt verhalten und Typ und Nachricht werden in Firefox und V8 (Chome, nodejs) korrekt gemeldet.Beachten Sie, dass ein zusätzlicher Eintrag vor dem ansonsten korrekten Stapel steht.
quelle
var a = new NotImplementedError('a'), b = new NotImplementedError('b');
. Jetzta instanceof NotImplementedError == false
undb instanceof NotImplementedError == true
Dies ist der schnellste Weg:
quelle
einfacher Weg. Sie können Ihr Objekt vom Fehlerobjekt erben lassen. Beispiel:
Wir verwenden den Funktionsaufruf (), der den Konstruktor der Error-Klasse aufruft. Dies entspricht im Wesentlichen der Implementierung einer Klassenvererbung in anderen objektorientierten Sprachen.
quelle
MDN hat ein hervorragendes Beispiel :
quelle