Z jakiegoś powodu wygląda na to, że delegowanie konstruktora nie działa w następującym fragmencie:
function NotImplementedError() {
Error.apply(this, arguments);
}
NotImplementedError.prototype = new Error();
var nie = new NotImplementedError("some message");
console.log("The message is: '"+nie.message+"'")
Uruchomienie tego daje The message is: ''
. Wszelkie pomysły, dlaczego lub czy istnieje lepszy sposób na utworzenie nowej Error
podklasy? Czy jest jakiś problem z apply
natywnym Error
konstruktorem, o którym nie wiem?
javascript
exception
cdleary
źródło
źródło
Odpowiedzi:
Zaktualizuj kod, aby przypisać prototyp do Error.prototype, a instanceof i twoje twierdzenia działają.
Jednak po prostu rzuciłbym własny obiekt i po prostu sprawdziłbym właściwość name.
Edytuj na podstawie komentarzy
Po zapoznaniu się z komentarzami i próbie przypomnienia sobie, dlaczego przypisałem prototyp do
Error.prototype
zamiastnew Error()
Nicholasa Zakasa w jego artykule , stworzyłem jsFiddle z poniższym kodem:Dane wyjściowe konsoli były takie.
Potwierdza to, że „problem”, na jaki natrafiłem, był właściwością stosu błędu był numer wiersza, w którym
new Error()
został utworzony, a niethrow e
miejsce wystąpienia. Może to jednak być lepsze niż efekt ubocznyNotImplementedError.prototype.name = "NotImplementedError"
linii wpływającej na obiekt Error.Zauważ też
NotImplementedError2
, że gdy nie ustawiam.name
jawnie, jest to równe „Błąd”. Jednak, jak wspomniano w komentarzach, ponieważ ta wersja ustawia prototyp nanew Error()
, mógłbym ustawićNotImplementedError2.prototype.name = "NotImplementedError2"
i być OK.źródło
Error.prototype
bezpośrednie przyjmowanie jest prawdopodobnie złą formą. Jeśli chcesz później dodaćNotImplementedError.prototype.toString
obiekt do aliasuError.prototype.toString
- lepiej to zrobićNotImplementedError.prototype = new Error()
.subclass.prototype = new Error()
jest złą postacią. Zamiast tego powinieneś użyćsubclass.prototype = Object.create(superclass.prototype)
. Mam nadzieję, że może to również rozwiązać problem śledzenia stosu.this.stack = new Error().stack;
NotImplementedError.prototype = Error.prototype;
, nie czyniinstanceof
traktująNotImplementedError
jako podklasy oError
, to czyniinstanceof
je traktować jako dokładnie tej samej klasy. Jeśli wkleisz powyższy kod do konsoli i spróbujesznew Error() instanceof NotImplementedError
uzyskaćtrue
, co jest oczywiście błędne.Wszystkie powyższe odpowiedzi są okropne - naprawdę. Nawet ten z 107 wzlotami! Prawdziwa odpowiedź jest tutaj:
Dziedziczenie po obiekcie Error - gdzie jest właściwość message?
TL; DR:
O.
message
Nie ustawiono powodu, żeError
jest to funkcja, która zwraca nowy obiekt Error i nie manipulujethis
w żaden sposób.B. Aby to zrobić, należy zwrócić wynik zastosowania z konstruktora, a także ustawić prototyp w zwykły skomplikowany sposób javascripty:
Można chyba zrobić kilka sztuczek wyliczyć przez wszystkich non-przeliczalnych właściwości
tmp
Error je ustawić zamiast jawnie ustawienie tylkostack
amessage
, ale oszustwo nie jest obsługiwana w IE <9źródło
return this
w konstruktorze.temp.name = this.name = 'MyError'
możesz zrobićtemp.name = this.name = this.constructor.name
. W ten sposób będzie działać również dla podklasMyError
.W ES2015 możesz
class
to zrobić czysto:Nie modyfikuje to globalnego
Error
prototypu, pozwala dostosowaćmessage
,name
i inne atrybuty, a właściwie oddaje stos. Jest również dość czytelny.Oczywiście może być konieczne użycie narzędzia, takiego jak
babel
kod działający w starszych przeglądarkach.źródło
Jeśli ktoś jest ciekawy, jak utworzyć niestandardowy błąd i uzyskać ślad stosu:
źródło
Ta sekcja standardu może wyjaśnić, dlaczego
Error.apply
wywołanie nie inicjuje obiektu:W takim przypadku
Error
funkcja prawdopodobnie określa, że nie jest wywoływana jako konstruktor, więc zwraca nową instancję Error zamiast zainicjowaćthis
obiekt.Testowanie za pomocą następującego kodu wydaje się wykazywać, że tak właśnie się dzieje:
Po uruchomieniu generowane są następujące dane wyjściowe:
źródło
this
inError.apply(this, arguments);
? Mówię, że wezwanie do błędu tutaj buduje nowy obiekt, który jest wyrzucany; nie inicjowanie już zbudowanego obiektu, do którego jest przypisanynie
.NotImplementedError
implementacja nie powinna zwrócićreturned
zmiennej?źródło
Miałem podobny problem do tego. Mój błąd musi być jednym i
instanceof
drugim , i musi także generować spójny ślad w konsoli.Error
NotImplemented
Moje rozwiązanie:
Wynik działania z node.js:
Błąd spełnia wszystkie 3 moje kryteria i chociaż
stack
właściwość jest niestandardowa, jest obsługiwana w większości nowszych przeglądarek, co jest dopuszczalne w moim przypadku.źródło
Zgodnie z Joyentem nie powinieneś zadzierać z właściwością stosu (co widzę w wielu podanych tutaj odpowiedziach), ponieważ będzie to miało negatywny wpływ na wydajność. Oto, co mówią:
Lubię i chciałbym wspomnieć ich pomijaniu oryginalnego błędu, który jest dobrym zamiennikiem przekazywania stosu.
Oto, w jaki sposób tworzę błąd niestandardowy, uwzględniając powyższe:
wersja es5:
wersja es6:
Umieściłem swoje rozwiązanie w module, oto on: https://www.npmjs.com/package/rerror
źródło
Lubię to robić w ten sposób:
"{code}: {message}"
error.code
ponieważ sprawdzanie / parsowanie kodu jest lepsze w kodzie niż sprawdzanie wiadomości, którą możesz chcieć zlokalizować na przykładerror.message
jako alternatywę dlaerror.toString()
źródło
Po prostu musiałem zaimplementować coś takiego i odkryłem, że stos został utracony w mojej własnej implementacji błędu. Musiałem stworzyć fałszywy błąd i pobrać z niego stos:
źródło
Użyłem Wzorca Konstruktora, aby utworzyć nowy obiekt błędu. Zdefiniowałem łańcuch prototypowy, taki jak
Error
instancja. Zobacz odniesienie do konstruktora błędów MDN .Możesz sprawdzić ten fragment o tym GIST .
REALIZACJA
STOSOWANIE
Konstruktor CustomError może odbierać wiele argumentów do zbudowania komunikatu, np
I tak wygląda błąd niestandardowy:
źródło
Konstruktor musi być jak metoda fabryczna i zwracać to, co chcesz. Jeśli potrzebujesz dodatkowych metod / właściwości, możesz dodać je do obiektu przed jego zwróceniem.
Chociaż nie jestem pewien, dlaczego miałbyś to zrobić. Dlaczego nie po prostu użyć
new Error...
? Wyjątki niestandardowe tak naprawdę nie dodają wiele w JavaScript (ani prawdopodobnie w żadnym nietypowym języku).źródło
Ładnie zaimplementowano to w Cesium DeveloperError:
W uproszczonej formie:
źródło
error instanceof Error
testu, co może być pomocne.To jest moja realizacja:
Przykładowe użycie nr 1:
Przykładowe użycie nr 2:
źródło
Kosztem niemożności użycia
instanceof
, poniższe zachowuje oryginalny ślad stosu i nie używa żadnych niestandardowych lew.źródło
fixError
powyższą funkcją. Dodanienew
podczas wywołania spowoduje po prostu utworzenie obiektu, który zostanie wyrzucony.Inna alternatywa, może nie działać we wszystkich środowiskach. Najpewniej zapewniam, że działa w nodejs 0.8 Podejście to wykorzystuje niestandardowy sposób modyfikowania wewnętrznego prototypu
źródło
Jeśli używasz Node / Chrome. Poniższy fragment kodu zapewni rozszerzenie spełniające następujące wymagania.
err instanceof Error
err instanceof CustomErrorType
[CustomErrorType]
po utworzeniu z komunikatem[CustomErrorType: message]
gdy zostanie utworzony bez komunikatuif
wyciągi i możesz już iść .Skrawek
Stosowanie
Wynik
źródło
Poniższe działało dla mnie zaczerpnięte z oficjalnego błędu dokumentacji Mozilli .
źródło
Wypróbuj nowy obiekt prototypowy dla każdej instancji typu błędu zdefiniowanego przez użytkownika. Pozwala
instanceof
to zachowywać się jak zwykle, a typ i komunikat są poprawnie zgłaszane w Firefox i V8 (Chome, nodejs).Zauważ, że dodatkowy wpis poprzedzi prawidłowy stos.
źródło
var a = new NotImplementedError('a'), b = new NotImplementedError('b');
. Teraza instanceof NotImplementedError == false
ib instanceof NotImplementedError == true
To najszybszy sposób na zrobienie tego:
źródło
łatwiejszy sposób. Możesz sprawić, że Twój obiekt odziedziczy po obiekcie Error. Przykład:
używamy funkcji call (), która wywołuje konstruktor klasy Error, więc jest to w zasadzie to samo, co implementacja dziedziczenia klas w innych językach obiektowych.
źródło
MDN ma doskonały przykład :
źródło