Creating A JavaScript Shim For Array Unshift() Method

Posted December 22, 2011 at 9:26 AM by Ben Nadel

Tags: Javascript / DHTML

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

Dec 22, 2011 at 9:48 AM // reply »
10 Comments

Next time go to w3fools.com. :P


Dec 22, 2011 at 9:51 AM // reply »
11,246 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!


Dec 23, 2011 at 11:06 AM // reply »
31 Comments

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...)


Dec 23, 2011 at 5:37 PM // reply »
2 Comments

I want to ask how to learn the basics of JavaScript?

Thanks!


Dec 27, 2011 at 9:10 AM // reply »
2 Comments

@Dean: There are many good introductory resources available online, for free. I've collected them here:
http://jscentral.org/links.html


Dec 27, 2011 at 9:12 AM // reply »
2 Comments

I'm a big fan of es5-shim [1] (which implements most ECMAScript 5 features on top of ECMAScript 3). It doesn't seem to add Array.prototype.unshift(), but maybe it should.

[1] https://github.com/kriskowal/es5-shim


Dec 27, 2011 at 9:22 AM // reply »
1 Comments

"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...


Dec 28, 2011 at 6:55 AM // reply »
2 Comments

Thanks Alex!


Dec 28, 2011 at 8:43 AM // reply »
11,246 Comments

@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.


Dec 28, 2011 at 10:52 AM // reply »
369 Comments

@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...


Dec 28, 2011 at 11:02 AM // reply »
11,246 Comments

@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.


Dec 28, 2011 at 4:13 PM // reply »
3 Comments

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 ;)


Dec 28, 2011 at 4:18 PM // reply »
11,246 Comments

@Thomas,

I'll try to carve out some time to make the updates.



Post A Comment

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.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 23, 2013 at 9:52 PM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Muhmmadibn Did you figure out a solution to launching PDFs? I am running into the same issues myself. There is no way to close the PDF or go back once you launch it. Thanks in advance! ... read »
May 23, 2013 at 6:06 PM
The Girl Who Broke My Heart, And Made Me A Better Person
Good day,ladies and gentle men, my name is Dr AMADI the great spell caster in Africa, i have help so many people for different kind of problems,who say there is no solution to problems on earth, that ... read »
May 23, 2013 at 4:26 PM
ColdFusion QueryAppend( qOne, qTwo )
@Heather, Glad people are still getting value out of this! ... read »
May 23, 2013 at 3:49 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, I meant the code at the bottom (not the video). I did try to experiment with an intermediary variable, like: value = users.id[ i ]; arrayContains( userIDs, value ); ... but t ... read »
May 23, 2013 at 11:06 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Are you talking about As Number: YES As String: YES As Java: YES? If so, that's with 3 different ways of referencing the constant 1, not users.id[1]. Query object references(*) are what seem ... read »
May 23, 2013 at 9:55 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dan, According to the CF Admin, I'm running Java "1.6.0_45". As far as the DB column, in the database it's an INT. I'll see if I can dig into what CF sees it as. @WebManWalking, But h ... read »
May 23, 2013 at 9:49 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, I think the problem is that we're used to loose typing in ColdFusion, like JavaScript. If a value is a number but it's needed in an expression to be a string, noooo problem. I've encountered ... read »
May 23, 2013 at 9:47 AM
ColdFusion QueryAppend( qOne, qTwo )
You rock! Thank you, thank you, thank you!!! ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools