With all due respect, you misunderstood how the prototype's behaviour.
Explaining everything would be too long a story, but concerning properties set on the prototype, it would be indeed a infinite source of bug if changing a property on an instance was changing this value for all instances.
Have a look, using jsfiddle, jsbin, cssdeck or whatever test site that you like, on your horse/dog example : the color of the dog is NOT changed when you change the horse's color. It is still black.
Why is that so ?
When an instance of dog does a READ access on a property, then it will be seeked on the prototype, then on the prototype's prototype, and so on until we reach the end of the prototype's chain. On the first value found, it will be returned, and if no property is found on no prototype, undefined is returned.
So right after an instance's creation, all animal colors will be null.
Now if you do a WRITE access on an instance's property, a brand new property will get created on this instance, and assigned the provided value. This way the prototype keeps its reference function, and the instance gets its value. Relief.
Still it is useful to define properties on the prototype, since :
1) you ensure all instances will provide a valid value for those properties -a default value-.
2) you can save memory by assigning once a property (and more importantly : a big object) that is shared amongst all instances (static). Expl : the default image for a dog.
3) you might want in some cases to change the values for all instances at once. In this case, changing the value on the prototype will do just that.
4) you allow the javascript interpreter to optimize your code by associating a class (in the C++ classic meaning) to your javascript class : when you assign a property existing on the prototype, the class is not 'broken', and the js interpreter can carry on using the background class to represent the instance. If performance matters, it is a very important point. If not, just forget about it :-)
So just a small example : if you define an animal, then each instance has its color and name : it make sense to have them set right in the constructor, and not on the prototype.
But for the leg count for instance, it will not change from an instance to another, and if you create child classes, you can always change the value on the children's prototype to have a children class change this count :
function Animal(name, color) {
this.name = name;
this.color = null;
}
Animal.prototype.legCount = 4; // most animal have 4 legs (...)
// Dog Class, inheriting from Animal
function Dog(name) { Animal.apply(this, arguments); }
// Set Animal as Dog's prototype's prototype.
// so that we can safely change Dog's prototype.
Dog.prototype = Object.create(Animal.prototype);
// Duck class
function Duck(name) { Animal.apply(this, arguments); }
// same inheritance scheme
Duck.prototype = Object.create(Animal.prototype);
// ... but we change the legCount, for the ducks only
Duck.prototype.legCount = 2;
Advanced answer :
If you want a prototype property to remain unchanged even
if we try to assign a value to this property on an instance, set
it as a readonly property on the prototype.
Object.defineProperty(Duck.prototype,'legCount', { get : function() { return 2 } } );
var duck = new Duck(...) ;
duck.legCount = 5;
console.log (duck.legCount) ; // --> output is still 2
If you want that setting the value on an instance change the value for
all instances (without explicitely change the prototype's property value), then
have it done in the setter of the prototype's property definition.
// using a closure
var duckLegCount = 2;
Object.defineProperty(Duck.prototype,'legCount', {
get : function() { return duckLegCount } ,
set : function (x) { duckLegCount = x } } );
var duck1 = new Duck(...);
var duck2 = new Duck(...);
duck1.legCount = 12;
console.log ( duck2.legCount ) ; // output is 12
public static int foo;in Java.prototype. Generally, functions and primitive values are safe. The changes won't be reflected across all instances. But with Objects, any changes made to properties of the object will be seen because objects are held by reference, and are mutable.