JavaScript Can Learn: Now Teach It Tricks!

When you do a lot of development with backend technologies, it can be frustrating to then move to the front end and feel like you are using a completely different syntax. One thing I really miss is the helper methods, especially when using Ruby on Rails on the server. Little helpers like titleize() or downcase() get replaced in javascript by a custom function and toLowerCase() respectively. You don’t have to feel lost anymore! There is a way you can extend the native objects found in JavaScript to make your environment feel a little more like “home.”

This is accomplished by using the prototype object. Each native object in JavaScript includes a prototype object. Don’t get this confused with the PrototypeJS framework… the prototype object is a way to extend all objects that have inherited from the base object you extended. You can easily extend the prototype object by adding functions to it like this:

Object.prototype.functionName = function(){

}

You can then call them directly:

var obj = new Object();
obj.functionName();

There are a number of advanced uses of the prototype object, but this is the important thing to remember: any function added to the prototype of an object is available on any object that inherits from it. So if you extend the prototype on the Number object, all numbers will have access to the new function; if you extend the Array object, all arrays can access your custom function. You only use the prototype.functionName syntax when declaring the new function, not when calling it.

Enough theory, lets see some (somewhat) practical uses:

Do you find yourself capitalizing a lot of words in a particular JavaScript app? Just add a capitalize method to the String object.

String.prototype.capitalize = function(){
  if(this.length == 0) return this;
  return this[0].toUpperCase() + this.substr(1);
}

Now you can capitalize any string in your application by calling "lower".capitalize() and get "Lower" in return. Since it returns a string, you could chain it with any other function you can execute on a string.

Do you always find yourself forgetting you can call Number(”25″) to turn a string into a number? Just add a toNumber() function to the String prototype:

String.prototype.toNumber = function(){
  return Number(this);
}

If you need to split large JSON arrays into groups of two or three each, you could extend the Array object like this:

[js]
Array.prototype.inGroupsOf = function(num){
	var ret = [],
		length = this.length,
		groups = Math.ceil(length / num);

	for(var i = 0; i < groups; i++){
		var start = i * num,
			end   = start + num;

		ret.push(this.slice(start, end))
	}
	return ret;
}

Now calling inGroupsOf(3) on any Array would return that same array split into as many parts as needed to ensure no group has more than three items in it.

There are a number of objects you can extend, but the ones you will use the most are String, Array, Object, Number, Date. One trouble area you might face is calling methods on numbers. The following example will fail:

Number.prototype.to_s = function(){
  return this + "";
}

25.to_s();

The prototype function is correct, but the way we called it is wrong. There are two ways to call our custom functions on numbers:

var n = 25;
n.to_s(); // Returns "25"

(25).to_s(); // Also returns "25"

Think Start, Not End

Its important when deciding what object to extend that you focus on what object type you are starting with, not so much which type you plan on ending with. For instance, if you wanted to extend an object to easily parse Twitter date strings you would not extend the Date object. You would extend the String object, and your function would return a Date object.

Load Your Extensions First

It is normally a good idea to load these extensions prior to any other library, including jQuery. Anytime you extend the prototype object, the new method is instantly available to all objects of the same type or any object that has inherited from that type. However, since you want to be sure your methods are always available, you guarantee their availability by loading them first.

How to Group The Extensions

Naming your files Prototype.Date.js and Prototype.Array.js is an easy way to keep all your extensions in one part of your JS folder, and easy to access during development. If you follow this method, you would simply put Date.prototype methods in the Prototype.Date.js file, etc. This starts to break down when you have parallel functions. You might have a toDateFromTwitter() method on the String object and a toTwitterFromDate() method on the Date object. Putting these in separate files might not make sense. At that point, you should put both these extensions in a file named TwitterHelpers.js or something similar. Obviously use what makes sense to you and works with your flow.

Don’t Bloat

Just because you write 500+ awesome Array extensions in the next 2 years, does not mean you need to include them on every project. Be sure to only use this technique when it makes sense for the project and when it helps clean up your code.

Doug Neiner is an Editor at Fuel Your Coding and an official member of the jQuery Team. He is addicted to new technology, and specifically loves spending time with WordPress, Ruby on Rails and jQuery. Learn more via twitter or his Google Profile.

 

If you liked this article, please help spread the news on the following sites:

  • Bump It
  • Blend It
  • Bookmark on Delicious
  • Stumble It
  • Float This
  • Reddit This
  • Share on FriendFeed
  • Clip to Evernote