12

What are the functional differences between the following two Javascript prototypes, and are there any benefits for choosing one over the other?

Option 1:

Person.prototype.sayName = function(name) {
   alert(name);
}

Option 2:

Person.prototype = {
   sayName: function(name) {
      alert(name);
   }
}

Am I correct in assuming that Option 2 results in trashing certain functions that are implicitly bound to the prototype?

Richard Keller
  • 1,980
  • 2
  • 19
  • 32
  • See also [What is the difference between these prototype declaration?](http://stackoverflow.com/questions/16773061/what-is-the-difference-between-these-prototype-declaration) – Bergi Mar 10 '14 at 18:51

5 Answers5

6

Am I correct in assuming that Option 2 results in trashing certain functions that are implicitly bound to the prototype?

Yes, exactly. Though the only implicitly bound property is the constructor property, which you seldom do need.

What are the functional differences?

Option 1 is just extending the existing prototype. If there are already Person instances inheriting from the prototype object, they will be able to use the sayName method as well. With option 2, the new prototype will only be used for objects that are instantiated after the overwriting.

Are there any benefits for choosing one over the other?

These should be self-explaining now. Option 1 (extending) is considered cleaner, and is a must if you're modifying foreign/unknown/native prototypes. Try to avoid option 2.

If you still like the object literal syntax better, you should consider using Object.assign to extend the existing prototype:

Object.assign(Person.prototype, {
   sayName: function(name) {
      alert(name);
   }
});

You may need to polyfill Object.assign for pre-ES6 environments. Alternatively, $.extend or _.extend work just as well. Surely also your favourite library comes with a helper function for this.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • why on earth should option 1 be considered cleaner. it appears to be that option 2 is the way to start with a clean slate so to speak. – Alexander Mills May 24 '15 at 16:18
  • 2
    @AlexMills: Because you don't need to know what properties do already exist on the prototype that you'd otherwise overwrite, and will not break them (regardless where the code is called). It's simpler, less error-prone and forwards-compatible. Of course, if you create a prototype object from scratch, you may as well use the object literal, but even then most people forget the standard `constructor` property. – Bergi May 24 '15 at 16:22
3

The second one will overwrite person.prototype with the object.

Method one:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype.sayName=function(){}
console.log(Person.prototype.constructor.toString());// "Person to string"

Method two:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype = {
  sayName:function(){}
}
console.log(Person.prototype.constructor.toString());// "Object to string"
HMR
  • 37,593
  • 24
  • 91
  • 160
2

The first is good for one or two extra functions, but defining a totally new prototype with many functions would be very repetitive. On the other hand, doing the latter would destroy all the existing definitions for the prototype as you mentioned.

In practice, I have used the first to define additional functions in Array and Math, etc., somewhat like categories in Objective-C. The latter I use as a "class definition."

isaach1000
  • 1,819
  • 1
  • 13
  • 18
  • 1
    I understand that when adding onto an existing code library (like Math) you wouldn't want to completely trash the prototype, but when creating a new library from scratch, is there any reason why I shouldn't trash the prototype? In other words, when I'm creating a new prototype, does it have any functions attached to it already, or is it just a blank placeholder? – Richard Keller Jul 04 '13 at 16:09
  • 1
    @RichardKeller You will overwrite the function's prototype with that of Object so you can't use `new this.constructor()` to create a new instance of `this`: http://phrogz.net/JS/classes/OOPinJS2.html – HMR Jul 04 '13 at 16:24
  • 1
    You are pretty safe with new prototypes. I tried experimenting in the Google Chrome console and I cannot destroy anything important. See this [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). – isaach1000 Jul 04 '13 at 16:47
1

Any existing instances of the constructor will continue pointing to the old prototype object. Any new instances created will point to the new prototype object.


The advantages of option 1 over option 2 are simply that you don't have to re-establish constructor property and you save one indentation level which is huge for me.

To save repetition, I just assign the property to a local variable:

var method = Person.prototype;

method.getAge = function() {
    return this.age;
};

method.getName = function() {
    return this.name;
};

Also common choices are fn (jQuery) and p which are even shorter than method.

Esailija
  • 138,174
  • 23
  • 272
  • 326
0

in simple words the difference is in Person.prototype.sayName all you do is to add a function to the prototype. just adding new functionality.

In the second Person.prototype = {} here you are making a new whole object and assign it to prototype. So you creating new object or overwrite the prototype with a new object.

First method is good to add many functions as you want on demand. You can add them each one on time, so i think it good when your program is simple and your application objects dose not share much functions or objects among them.

Second method is good if your application objects share some objects(or group of functions as @isaach said in Math functions) among them.

ebram khalil
  • 8,252
  • 7
  • 42
  • 60