Augmenting built-in objects through the prototype is a very powerful technique and you can use it to shape JavaScript any way you like. But modifying core objects could only confuse the user of the library and create unexpected errors.
The JavaScript changes and browsers come up with new versions that support more features.
To reverse strings there is no built-in reverse() method for string objects. After all, arrays have reverse(). You can easily add this reverse() method to the String prototype, borrowing Array.prototype.reverse(). The below code uses split() to create an array from a string, then calls the reverse() method on this array, which produces a reversed array.
String.prototype.reverse = function() { return Array.prototype.reverse.apply(this.split('')).join(''); }
"Stoyan".reverse(); "nayotS"
When you decide to augment the prototype of built-in objects with a new property check for existence of the new property before implementing it.
if (!String.prototype.reverse) { String.prototype.reverse = function() { return Array.prototype.reverse.apply(this.split('')).join(''); } }
Here are two interesting behaviors to consider when dealing with prototypes:
Creating a simple constructor function and two objects.
function Dog(){this.tail = true;} var benji = new Dog(); var rusty = new Dog();
Even after you create the objects, you can still add properties to the prototype and the objects will have access to the new properties. Let's throw in the method say():
Dog.prototype.say = function() { return 'Woof!'; }
Both objects have access to the new method:
benji.say(); "Woof!" rusty.say(); "Woof!"
If you check your objects, asking which constructor function was used to create them, they'll report it correctly.
benji.constructor; Dog() rusty.constructor; Dog()
But if you ask what is the constructor of the prototype object, you'll also get Dog(), which is not quite correct. The prototype is just a normal object created with Object(). It doesn't have any of the properties of an object constructed with Dog().
benji.constructor.prototype.constructor Dog() typeof benji.constructor.prototype.tail "undefined"
Now overwrite the prototype object with a new object.
Dog.prototype = {paws: 4, hair: true};
Now the old objects do not get access to the new prototype's properties, they still keep the secret link pointing to the old prototype object.
typeof benji.paws "undefined" benji.say() "Woof!" typeof benji.__proto__.say "function" typeof benji.__proto__.paws "undefined"
Any new objects you create from now on will use the updated prototype.
var lucy = new Dog(); lucy.say() TypeError: lucy.say is not a function lucy.paws 4
The secret __proto__ link points to the new prototype object.
typeof lucy.__proto__.say "undefined" typeof lucy.__proto__.paws "number"
Now the constructor property of the new objects reports wrongly. It should point to Dog(), but instead it points to Object().
lucy.constructor Object() benji.constructor Dog()
The prototype of the constructor is the confusing part.
typeof lucy.constructor.prototype.paws "undefined" typeof benji.constructor.prototype.paws "number"
The following code fixed all of the unexpected behavior described above.
Dog.prototype = {paws: 4, hair: true}; Dog.prototype.constructor = Dog;