2013-07-08 21 views
6

Stavo sviluppando una piccola libreria JS e dovevo utilizzare le eccezioni di errore personalizzate.Estensione errori/eccezioni JavaScript

Così, ho deciso di ereditare loro di natale oggetto errore JavaScript in questo modo (ORLY?):

var MyError = function(){ 
    Error.prototype.constructor.apply(this, arguments); 
}; 

// Inherit without instantiating Error 
var Surrogate = function(){}; 
Surrogate.prototype = Error.prototype; 
MyError.prototype = new Surrogate(); 

// Add some original methods 
MyError.prototype.uniqueMethod = function(){...} 

Sembra che al solito eredità .. Ma!

var err = new MyError("hello! this is text!"); 
console.log(err.message); // is giving me empty string! 

Ho letto articoli su questo here e sulle MDN, ma tutti loro dicendo me di utilizzare qualcosa di simile:

var MyError = function(msg){ 
    this.message = msg; 
}; 

Ma la mia domanda è - se non nel costruttore di errore, allora dove il messaggio è inizializzato? Qualcuno sa come funziona il costruttore nativo di Error?

Grazie!

P.S. Se è interessante, stavo sviluppando la libreria Enum.js.

+1

Rendere più semplice possibile: 'var obj = new Errore(); Error.call (obj, "Hello, world!"); ' Questo non funziona neanche. "Errore" è strano. – Ryan

+1

@minitech: * "Errore" è strano. "* +1 –

risposta

5

Quello che stai facendo va bene. È il Error questo è il problema.

Su questa linea:

Error.prototype.constructor.apply(this, arguments); 

... si sta chiamando Error (indirettamente) come una normale chiamata di funzione piuttosto che come parte di un'espressione new, e il defined behavior for Error when you call it as a non-constructor function è quello di creare un nuovo, vuoto Error e restituirlo (anziché compilare this).

Ora, nel caso normale, ciò che si sta facendo con il prototipo farebbe funzionare il controllo standard per stabilire se è stato chiamato come costruttore (if (this instanceof Error)). Sfortunatamente, non sembra che lo stia facendo, e qualunque controllo utilizzi per determinare come è stato chiamato non sembra essere immediatamente sensibile a ciò che stai cercando di fare. Anche questo (che è solo un test, non vuole essere qualcosa che ci si effettivamente fare):

MyError.prototype = Error.prototype; // You wouldn't normally do this, it's just a test 

... non risolverlo.

This answer to another Stack Overflow question indica una possibile soluzione (in pratica, consentono Error creare l'oggetto e poi tornare che da MyError):

function MyError(message) { 
    var e = new Error(message); 
    // ...apply your enhancements to `e` 
    return e; 
} 

Non sorprendentemente soddisfacente come ci si deve mettere le estensioni direttamente sull'oggetto piuttosto che usare la catena di prototipi, ma se Error refusées a giocare a palla, le opzioni sono un po 'limitato ...

+0

Grazie per la risposta. Quindi, sembra che devo fare smth come: 'MyError = function (msg) {var err = new Error(); this.msg = msg; this.stack = err.stack; ...} – gobwas

+0

@gobwas: ho appena aggiornato la risposta con una possibile soluzione alternativa. Non mi piace, ma non sono sicuro che tu abbia molta scelta. * Modifica * Oppure, sì, potresti farlo in questo modo. –

+1

grazie mille, e sì, non ci sono molte scelte =)) – gobwas