Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Adam Tuttle

Creating A JavaScript Shim For Array Unshift() Method

By Ben Nadel on

If you write JavaScript, chances are good that you're familiar with the push() and pop() methods of an Array. These methods add and remove items to and from the end of an array, respectively. You might, however, not be as familiar with the unshift() and shift() methods of an Array. These add and remove items to and from the beginning of an array, respectively. Unshift() is a pretty awesome function; so, when I realized yesterday that I tend to use the more complex splice() method in order to achieve unshift() functionality, I was saddened.


 
 
 

 
I find that I often think of using splice() before I think of using unshift() on JavaScript arrays. This saddens me. 
 
 
 

In a response to my tweet, Aaron Cox told me that my instinct was probably good since, according to the W3C Schools website, unshift() is not actually supported in Internet Explorer (IE). Upon some subsequent testing and Googling, however, I found the W3C site to not be so accurate. Other sites do state full browser support; and, testing in my own IE 9 and IETester apps, I failed to find any occurrences where unshift() was not supported.

That said, the functionality of the unshift() method can be easily reproduced using the splice() method. As such, I thought it would be fun to write a quick shim that would implement unshift() support in any browser that didn't support it natively:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Creating A JavaScript Shim For Array Unshift() Method</title>
  •  
  • <script type="text/javascript">
  •  
  •  
  • // For testing, delete the native unshift method.
  • delete( Array.prototype.unshift );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // Check to see if this browser supports the unshift()
  • // method of the Array class.
  • if (!Array.prototype.hasOwnProperty( "unshift" )){
  •  
  • // We are working with a partially-disabled browser;
  • // let's fill in the unshift() method.
  • Array.prototype.unshift = function(){
  •  
  • // The unshift() method can take N-arguments to push
  • // onto the front of the array. We can use splice()
  • // under the hood to carry out this funciton. Prepare
  • // the splice() arguments by adding two zeros: one
  • // for the zero index and one for the delete count.
  • Array.prototype.splice.call( arguments, 0, 0, 0, 0 );
  •  
  • // Splice the "unshifted" values into place.
  • Array.prototype.splice.apply( this, arguments );
  •  
  • // For debuging....
  • console.log( "Unshifting...." );
  •  
  • // Return new length of unshifted array.
  • //
  • // NOTE: This return value does not seem to be
  • // consistent across browsers. Firefox returns an
  • // empty array natively.
  • return( this.length );
  •  
  • };
  •  
  • }
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // Create an empty array.
  • var collection = [];
  •  
  • // Push a few items onto the end.
  • collection.push( "End1", "End2" );
  •  
  • // Push a few items onto the beginning using unshift().
  • collection.unshift( "Begin1", "Begin2" );
  •  
  • // Log the result.
  • console.log( collection );
  •  
  •  
  • </script>
  •  
  • </head>
  • <body>
  • <!-- Left intentionally blank. -->
  • </body>
  • </html>

In this demo, you can see that I am starting out by deleting the native unshift() method. Then, I replace it with my splice()-powered shim. Since splice() can be used to both delete and insert items, unshift() can be thought of as splicing values onto the front of an array.

When we run the above code, we get the following console output:

Unshifting....
["Begin1", "Begin2", "End1", "End2"]

As you can see, this works quite nicely. Necessary or not, this was a fun little snippet of code to write. The splice() method is incredibly powerful, which is why I tend to think of it. If you ever read JavaScript: The Good Parts by Douglas Crockford, you'll actually see a number of Array methods that can be reproduced using the splice() method.




Reader Comments

@Wilkins,

Ha ha, I had never even heard of that before. Looks like an awesome resource to fill in / make up for the gaps. The W3C Schools website has helped me a lot of the past few years; but it definitely has some buggy information and lacking examples.

Thanks for the link!

Reply to this Comment

Javascript....

JAVASCRIPT?!?!

Get back to the good stuff Ben! You're Nadel; King of the Cold(Fusion). What's with all this JS quackery?

(Ok, ok, I realize that as an application developer, you're getting into an area that's new and exciting for you, and it only makes sense that you'd make blog posts about something that interests you, so all I'm asking is for you not to forget your roots) :)

Now...if you'll excuse me, I need to get back to figuring out why my THIS scope variables are not being set in my app.cfc. I'm on day 3...

<reserved_snooty_but_respectful_attitude>
Good DAY, sir!
</reserved_snooty_but_respectful_attitude>

(And yeah, I know that tag doesn't validate...)

Reply to this Comment

"In a response to my tweet, Aaron Cox told me that my instinct was probably good since, according to the W3C Schools website, unshift() is not actually supported in Internet Explorer (IE). Upon some subsequent testing and Googling, however, I found the W3C site to not be so accurate"

Please go again on w3fools and note that www.w3schools.com isn't related at all with the W3C, so the "W3C Schools website" does not exist.

BTW, it seems Array.prototype.unshift is supported since IE 5.5...

Reply to this Comment

@Aaron,

Ha ha, I still love ColdFusion :) I swear! I just happen to code a lot of JavaScript these days. ColdFusion is still my main girl :D

@Axel,

That ES5-shim looks pretty robust. As I scroll through the code, it's definitely much more in-depth that I would have even thought to make some of those functions. Good link!

@Check_ca,

Ah, good point. I didn't truly understand the relationship between the two sites. I assumed they were related based on naming. Thanks for pointing out the truth of the matter.

Reply to this Comment

@Aaron & @Ben,

I am coding a lot more JavaScript these days, mainly because we control the users' browsers and what they "allow" and "don't allow"...in the way of allowing JavaScript, etc., but I have to admit, it's kind of a pain to have to code in both JavaScript AND a server-side language when you have to accomodate the users/clients. (especially when time is of the essence in development). Maybe that makes me sound lazy...

Reply to this Comment

@Anna,

It's kind of annoying to have to both server-side and client-side validation; but, as I have gotten into this more, I've started to realize that you can make the server-side validation much less "user friendly" since your client-side validation will take care of being more user friendly.

Hmm, that's actually an interesting topic to write about.

Reply to this Comment

Hi Ben!

Please, update your article to clarify the terms "W3C Schools" and the relation between W3Schools and the W3C. Not everyone will read the comment ;) And I'm encouraging to mention w3fools directly in the article too ;)

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.