Defining a Javascript prototype

2018-12-31 14:08发布

问题:

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?

回答1:

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.



回答2:

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\"


回答3:

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.\"



回答4:

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.



回答5:

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.