0

Take this example:

 var personPrototype = { 
 firstName: '',
 lastName: '',

 getFullname: function() { 
    return this.firstName + ' : ' + this.lastName; 
  } 
} 

Person = {

};

function newPerson(firstName, lastName) { 
    var Person = function(firstName, lastName) { 
      this.firstName = firstName; 
      this.lastName = lastName; 
    }
    Person.prototype = personPrototype;
    return new Person(firstName, lastName);
}

var p1 = newPerson('someone', 'else');
var p2 = newPerson('john', 'doe');
console.log(p1.getFullname());
console.log(p2.getFullname());

Moving the firstName and lastName from the personPrototype to the Person yields the same results. Does that mean that there is no difference between the two, or am I overlooking something?

dexter
  • 738
  • 2
  • 10
  • 19
  • You should not re-create the `Person` constructor every time in that `newPerson` factory function. If you want to use factory functions, [use `Object.create`](http://stackoverflow.com/a/39546963/1048572) instead. – Bergi Sep 19 '16 at 10:50

1 Answers1

1

The difference between properties put directly on an object and properties put on the prototype of an object is quite significant. The prototype is shared by all instances of an object. Properties defined in the object (as in within a constructor function) will be defined on each instance.

I suspect that you are getting confused when defining your Person object. The Person in the global scope is being overridden by your constructor function inside newPerson and is never used. You don't need to define your properties at all outside of your constructor/method functions unless you have a specific reason to share a value between all instances of the object.

As for why defining the properties in the prototype makes no difference: it's the prototype chain. When you define firstName et al in personPrototype and then also in the constructor function it is overridden. So calling getFullName falls back to personPrototype and then looks for lastName on the current instance of Person thus picking up the value passed when you call new Person(firstName, lastName).

user2005218
  • 193
  • 1
  • 9
  • What do you mean by "more OOP"? Smalltalk? – Bergi Sep 19 '16 at 10:51
  • I mean a language that is more formally object oriented, like Java, where you have to detail the class structure outside of the constructor method. But it's just speculative and doesn't really add anything to the answer so I have removed it. – user2005218 Sep 19 '16 at 11:00
  • Thanks, actually the part that is (still a bit) confusing to me is that I would suspect the properties in the prototype to be shared by all instances. Similar to static properties in C++ (they are actually properties at the class level). So, then I would expect the properties to be shared by the different instances and thus be overwritten such that both p1 and p2 would be John Doe. But that is not the case. – dexter Sep 19 '16 at 11:20
  • @dexter They are shared indeed - every instance inherits the empty strings from the prototype properties. But when you assign to an object property, an *own* property is created on the object itself, which then shadows the inherited one. If you want to overwrite the shared one, you'd have to assign to `personPrototype.name` explicitly. – Bergi Sep 19 '16 at 11:39
  • 1
    @user2005218 yes, class-oriented would be the more appropriate term. Some people even consider Java to be less object-oriented than JavaScript because classes and methods are no objects. – Bergi Sep 19 '16 at 11:41
  • Yes, that is because of the prototype chain. The object instance has precedence over the prototype. Similarly, if you defined `getFullName` in the `Person` constructor it would call that function instead of the one defined in the prototype. – user2005218 Sep 19 '16 at 11:42
  • @Bergi Ah, I could definitely see the argument for that. Rather, I'd even agree with it now that I think about it that way. Thanks! – user2005218 Sep 19 '16 at 11:46
  • @bergi very nice, thank you – dexter Sep 19 '16 at 19:31