Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property on the prototype overrides the property of the actual object?

I have a Person constructor function like so with the method sayHello

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

Then I define a different version of the sayHello method on the prototype of Person:

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

Now if I create a Person instance and call sayHello on it - I notice that it is using the version of sayHello which is defined on the prototype.

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

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

This to me is confusing.

Why doesn't the JoeBlow object use its own implementation of sayHello, instead of looking up sayHello on its prototype object?

like image 703
Danield Avatar asked Nov 23 '15 13:11

Danield


1 Answers

By default, properties defined with defineProperties are read only.

See MDN

writable
true if and only if the value associated with the property may be changed with an assignment operator.
Defaults to false.

Unfortunately, when you attempt to set a read only property in old style JS, it fails silently rather than throwing an exception, so this is really hard to debug.

If you had run this in strict mode you would have got:

TypeError: Cannot assign to read only property 'sayHello' of [object Object]

You can explicitly define the property to be writable.

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

Then this.sayHello = function() { won't fail silently and you'll successfully mask the version of the property living on the prototype.

like image 142
Quentin Avatar answered Oct 17 '22 15:10

Quentin