Búsqueda de sitios web

javascript - ¿La propiedad en el prototipo sobrescribe la propiedad del objeto real?


Tengo una función constructora Person así con el método sayHello

var Person = function(firstName,lastName) {
  this.lastName = lastName;
  this.sayHello = function() {
    return "Hi there " + firstName;
  }
};

Luego defino una versión diferente del método sayHello en el prototipo de Person:

Object.defineProperties(Person.prototype,{
  sayHello: {
    value: function() {
      return 'Hi there';
    },
    enumerable: true
  }
});

Ahora, si creo una instancia de Persona y llamo a sayHello en ella, noto que está usando la versión de sayHello que está definida en el prototipo.

var JoeBlow = new Person('Joe','Blow');

> JoeBlow.sayHello() 
< "Hi there" // I was expecting "Hi there Joe"

Esto para mí es confuso.

¿Por qué el objeto JoeBlow no usa su propia implementación de sayHello, en lugar de buscar sayHello en su objeto prototipo?

Respuesta #1

Por defecto, las propiedades definidas con defineProperties son solo lectura.

Ver MDN

editable
verdadero si y solo si el valor asociado con la propiedad puede ser cambiado con un operador de asignación.
Por defecto es falso.

Desafortunadamente, cuando intentas establecer una propiedad de solo lectura en JS antiguo, falla silenciosamente en lugar de lanzar una excepción, por lo que esto es realmente difícil de depurar.

Si hubieras ejecutado esto en modo estricto, habrías obtenido:

TypeError: No se puede asignar a la propiedad de solo lectura 'sayHello' de [object Object]

Puedes definir explícitamente que la propiedad sea escribible.

Object.defineProperties(Person.prototype,{
  sayHello: {
    value: function() {
      return 'Hi there';
    },
    enumerable: true,
    writable: true
  }
});

Entonces this.sayHello=function() { no fallará silenciosamente y enmascararás con éxito la versión de la propiedad que vive en el prototipo.