No puedo entender cómo se definen las propiedades de error. Algunos se definen en la instancia, algunos se definen en el prototipo. ¿No debería ser imposible? Quiero decir, esperaría que una instancia recién creada tuviera exactamente las mismas propiedades que el prototipo. Esto es lo que quiero decir:
let err = new Error('Test'); Object.getOwnPropertyNames(err); // Array(4) [ "fileName", "lineNumber", "columnNumber", "message" ] Object.getOwnPropertyNames(Object.getPrototypeOf(err)); // Array(5) [ "toString", "message", "name", "stack", "constructor" ] ¿Cómo es posible que fileName , lineNumber , columnNumber existan en la instancia, pero no existan en el prototipo si la instancia acaba de crearse y no se modificó de ninguna manera?
Además, la instancia no tiene la stack como propiedad propia, ¿es porque no es enumerable?
¿Cómo es posible que fileName, lineNumber, columnNumber existan en la instancia, pero no existan en el prototipo si la instancia acaba de crearse y no se modificó de ninguna manera?
No hay nada mágico pasando aquí. Error es una función constructora. Esa función puede crear cualquier propiedad en la instancia.
Ejemplo:
class Error { constructor() { this.fileName = '<script>'; } } const err = new Error(); console.log(Object.getOwnPropertyNames(err)); console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(err))); Como puede ver, fileName es una propiedad que solo existe en la instancia.
¿No debería ser imposible? Quiero decir, esperaría que una instancia recién creada tuviera exactamente las mismas propiedades que el prototipo.
No es así como se supone que debe funcionar. El prototipo contiene propiedades que deben compartirse entre todas las instancias y la instancia contiene propiedades específicas de esa instancia. Al final, un prototipo es solo un objeto al que apunta otro objeto (la instancia). Solo se usa cuando se accede a una propiedad en la instancia. Si esa propiedad no existe en la instancia, el tiempo de ejecución de JS la buscará en el prototipo de la instancia, etc. Nada más y nada menos.
Tal vez te sorprenda ver un message en la instancia y el prototipo. La propiedad del message en el prototipo es el mensaje de error predeterminado. Se usa si la instancia de error no tiene un mensaje propio (si no pasa un argumento al constructor de Error , la instancia de error no tiene una propiedad de message propia (consulte la especificación )).
const err = new Error(); console.log(Object.getOwnPropertyNames(err)); console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(err)));Además, la instancia no tiene la pila como propiedad propia, ¿es porque no es enumerable?
No, una propiedad "propia" es una propiedad "propia" independientemente de su enumerabilidad. stack es un getter/setter y, por lo tanto, puede operar en la instancia actual a través de this (o sin embargo, esa funcionalidad se implementa para funciones nativas).
console.log(Object.getOwnPropertyDescriptor(Error.prototype, 'stack')); // Object { get: stack(), set: stack(), enumerable: false, configurable: true }