validacion recorrer objetos objeto lista herencia formularios ejemplos crear con clases array agregar javascript

javascript - recorrer - Heredar desde el objeto Error-¿dónde está la propiedad del mensaje?



recorrer array de objetos javascript (7)

¿Qué hay de malo en hacerlo de esta manera en ES6?

class MyError extends Error { constructor(message) { super(message); // Maintains proper stack trace (only on V8) if (Error.captureStackTrace) { Error.captureStackTrace(this, MyError); } this.appcode= 123; // can add custom props } }

Noté un comportamiento extraño al definir objetos de error personalizados en Javascript:

function MyError(msg) { Error.call(this, msg); this.name = "MyError"; } MyError.prototype.__proto__ = Error.prototype; var error = new Error("message"); error.message; // "message" var myError = new MyError("message"); myError instanceof Error; // true myError.message; // "" !

¿Por qué el new Error("message") establece la propiedad del message , mientras que Error.call(this, msg); ¿no? Claro, puedo definir this.message = msg en el constructor MyError , pero no entiendo por qué no está ya configurado en primer lugar.


En Node.js puedes crear un error personalizado como este:

var util = require(''util''); function MyError(message) { this.message = message; Error.captureStackTrace(this, MyError); } util.inherits(MyError, Error); MyError.prototype.name = ''MyError'';

Consulte captureStackTrace en documentos de nodo


Me gusta mucho crear archivos .js reutilizables que pongo en casi cualquier proyecto en el que participe. Cuando tenga tiempo, se convertirá en un módulo.

Para mis errores, creo un archivo exceptions.js y lo agrego a mis archivos.

Aquí está el ejemplo del código dentro de este archivo:

const util = require(''util''); /** * This exception should be used when some phat of code is not implemented. * @param {String} message Error message that will be used inside error. * @inheritDoc Error */ function NotImplementedException(message) { this.message = message; Error.captureStackTrace(this, NotImplementedException); } util.inherits(NotImplementedException, Error); NotImplementedException.prototype.name = ''NotImplementedException''; module.exports = { NotImplementedException, };

En los otros archivos de mi proyecto, debo tener esta línea requerida en la parte superior del archivo.

const Exceptions = require(''./exceptions.js'');

Y para usar este error solo necesitas esto.

const err = Exceptions.NotImplementedException(`Request token ${requestToken}: The "${operation}" from "${partner}" does not exist.`);

Ejemplo de implementación de método completo

const notImplemented = (requestToken, operation, partner) => { logger.warn(`Request token ${requestToken}: To "${operation}" received from "${partner}"`); return new Promise((resolve, reject) => { const err = Exceptions.NotImplementedException(`Request token ${requestToken}: The "${operation}" from "${partner}" does not exist.`); logger.error(err.message); return reject(err); }); };


Otro enfoque para esto es hacer de la nueva instancia de error el prototipo de this , y de esa manera no tiene que saber qué propiedades copiar, lo que evita los problemas de los que BT habló al final de su respuesta.

function MyError() { if (this === undefined) { throw TypeError("MyError must be called as a constructor"); } let newErr = Error.apply(undefined, arguments); Object.setPrototypeOf(newErr, MyError.prototype); Object.setPrototypeOf(this, newErr); } MyError.prototype = Object.create(Error.prototype); let me = new MyError("A terrible thing happened"); console.log(me instanceof MyError); // true console.log(me instanceof Error); // true console.log(me.message); // A terrible thing happened

Y por mi dinero, es un poco mejor. Pero tenga en cuenta que Object.setPrototypeOf() (u object.__proto__ = en implementaciones no compatibles con ES6 que lo admiten) puede ser muy lento, por lo que si está utilizando estos errores en sus rutas doradas, es posible que no desee hacerlo.


Puede usar Error.captureStackTrace para filtrar la línea innecesaria en el seguimiento de la pila.

function MyError() { var tmp = Error.apply(this, arguments); tmp.name = this.name = ''MyError''; this.message = tmp.message; /*this.stack = */Object.defineProperty(this, ''stack'', { // getter for more optimizy goodness get: function() { return tmp.stack; } }); Error.captureStackTrace(this, MyError); // showing stack trace up to instantiation of Error excluding it. 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 ...>


R. Como, dijo Raynos, el message motivo por el message no se establece es que Error es una función que devuelve un nuevo objeto Error y no lo manipula de ninguna manera.

B. La forma de hacerlo bien es establecer el resultado de la aplicación del constructor en this , así como configurar el prototipo de la manera habitual javascripty complicado:

function MyError() { var tmp = Error.apply(this, arguments) tmp.name = this.name = ''MyError'' this.message = tmp.message // instead of this.stack = ..., a getter for more optimizy goodness Object.defineProperty(this, ''stack'', { get: function () { return tmp.stack } }) 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 ...>

Los únicos problemas con esta forma de hacerlo en este punto (lo he iterado un poco) son que

  • las propiedades distintas de la stack y el message no están incluidas en MyError , y
  • el stacktrace tiene una línea adicional que no es realmente necesaria.

El primer problema podría solucionarse iterando a través de todas las propiedades de error no enumerables usando el truco de esta respuesta: ¿Es posible obtener los nombres de propiedades heredadas no enumerables de un objeto? , pero esto no es compatible con, por ejemplo, <9. El segundo problema podría resolverse arrancando esa línea en el seguimiento de la pila, pero no estoy seguro de cómo hacerlo de manera segura (tal vez simplemente eliminando la segunda línea de e.stack.toString () ??).

Actualizar

Creé una biblioteca de herencia que hace esto ^ https://github.com/fresheneesz/proto


function MyError(msg) { var err = Error.call(this, msg); err.name = "MyError"; return err; }

Error no lo manipula, crea un nuevo objeto de error que se devuelve. Es por eso que Error("foo") también funciona sin la new palabra clave.

Tenga en cuenta que esto es específico de la implementación, v8 (chrome & node.js) se comporta así.

También MyError.prototype.__proto__ = Error.prototype; es una mala práctica Utilizar

MyError.prototype = Object.create(Error.prototype, { constructor: { value: MyError } });