Extending Built-in Objects in JavaScript

As you know very well by now, JavaScript comes from the
factory with a good supply of built-in objects. These objects provide
some of the core functionality for working with text, numbers,
collections of data, dates, and a whole lot more. As you become
more familiar with JavaScript and start doing interesting-er and
cleverer things, you'll often find that you want to do more and go
farther than what the built-in objects allow.

Let's take a look at an example of when something like this might
occur. Earlier, in the
Shuffling an Array tutorial, you saw how to shuffle the contents of
an array:

After this code has run, the end result is that the contents of your array
are now rearranged.
Now, this functionality is pretty useful. I would say this is sooo
useful, the shuffling ability should be a part of the
Array object and be as easily accessible
as push,
pop, slice,
and other doo-dads the Array object has.

If the shuffle function were a part
of the Array object, you could simply
use it as follows:

var tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
tempArray.shuffle();

This is an example of us extending a built-in object (the
Array) with some functionality that we
defined (the shuffle). In this
tutorial, we are going to look at how exactly to accomplish this, why it
all works, and why extending built-in objects is pretty controversial.

Onwards!

Say Hello to prototype...again. Sort
of!

Extending a built-in object with new functionality sounds
complicated, but it is really simple once you understand what needs to
be done. To help with this, we are going to look at a combination of
sample code and diagrams all involving the very friendly
Array object:

Um...anyway, let's say that we have the following code:

var tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

If we were to diagram the full hierarchy of the
tempArray object, it would look as
follows:

On the left, we have our tempArray
object that is an instance of Array. The
built-in Array object is derived from
the basic Object type. Now, what we want
to do is extend the Array object with
our shuffle function. What this means is that we need to figure out a
way to get our shuffle function inserted into our
Array object itself:

Here is the part where the quirkiness of JavaScript shines through.
We don't have access to the Array object
source code. We can't find the function or object that makes up the
Array and insert our shuffle function
into it like we might for a custom object that we defined. Your built-in
objects, such as the Array, are defined
deep inside your browser's volcanic underbelly where no human being can
go. We need to take another approach.

That another approach involves casually sneaking
in and attaching your functionality by using the
Array object's prototype
property. That would look something like this:

Notice that our shuffle function is
declared on Array.prototype! As part of
this attachment, we made a minor change to how the function works. The
function no longer takes an argument for
referencing the array you need shuffled:

function shuffle(input) {
.
.
.
.
.
}

Instead, because this function is now a part of the
Array, the this
keyword inside the function body points to the array that needs
shuffling:

Array.prototype.shuffle = function () {
var input = this;
.
.
.
.
}

Taking a step back, once you run this code, your shuffle
function will find itself shoulder-to-shoulder with all of the other
built-in methods the Array object
provides:

If you wanted to access the shuffle
function (err...method!), you can now do so using the approach we had
initially desired:

var tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
tempArray.shuffle();

This is because the prototype
property provides you with direct access to your
Array's insides. Declaring the
shuffle function on it gave us the
result we wanted. Best of all, any new arrays you create will also have
access to the shuffle functionality by default thanks to how prototype
inheritance works.

Extending Built-in Objects is Controversial

Given how easy it is to extend a built-in object's functionality by
declaring methods and properties using the
prototype property, it's easy to think that everybody loves the
ability to do all of this. As it turns out, extending built-in objects
is a bit controversial. The reasons for this controversy revolve
around...

You Don't Control the Built-in Object's Future

There is nothing preventing a future implementation of JavaScript
from including its own version of shuffle that applies to
Array objects. At this point, you have a
collision where your version of shuffle
and the browser's version of shuffle are
in conflict with each other - especially if their behavior or
performance characteristics wildly differ. Rut roh!

Some Functionality Should Not Be Extended or Overriden

Nothing prevents you from using what you've learned here to modify
the behavior of existing methods and properties. For example, this is me
changing how the slice behavior works:

Further Reading

Conclusion - What Should You Do?

My answer to what you need to do is simple: Use your best
judgment!. The two cases I outlined are only part of the
various issues that people raise when extending built-in objects is
discussed. For the most part, all of the objections are valid. The
question you need to ask is, "Are these objections valid for my particular scenario?" My guess
is that they probably won't be.

From personal experience, I have never had any issues extending
built-in objects with my own functionality. I wrote this
shuffle function years ago, and no browser as of now has even hinted at
implementing their own version of it. I am certainly not complaining!
Second, for any functionality I do add, I test to make sure that it
works well across the browsers I am currently targeting. As long as your
testing is somewhat comprehensive (probably the latest one or two
versions of the major browsers), you should be good to go.

If you are worried about future-proofing, name any properties or
methods in a way that only your app would use it. For example, the
chances of Array.prototype.kirupaShuffle
being introduced by any future browser release is pretty close to zero
:P

Did You Like This?

Getting Help

If you have questions, need some assistance on this topic, or just want to
chat - post in the comments below or drop by our friendly forums
(where you have a lot more formatting options) and post your question. There are
a lot of knowledgeable and witty people who would be happy to help you out

Share

Did you enjoy reading this and found it useful? If so, please share it with
your friends:

If you didn't like it, I always like to hear how I can do better next time.
Please feel free to contact me directly at kirupa[at]kirupa.com.