Adding A Splice() Method To The Javascript String Prototype

Posted March 29, 2011 at 10:53 AM by Ben Nadel

Tags: Javascript / DHTML

In my blog post yesterday on using slice(), substring(), and substr() in Javascript to perform substring extraction, Andy Matthews and I got into a brief discussion about how in many languages, at a core level, strings are nothing more than arrays of characters. This concept got me thinking - if both Arrays and Strings in Javascript have a slice() method, then why don't they both have a splice() method? For fun, I wanted to see how easy it would be to modify the String prototype, adding our own splice() method.

Javascript already supports splice() on arrays. So, rather than re-inventing the wheel for strings, I figured the smartest move would be to convert our target string into an array and then leverage the already-powerful array-based splicing. Luckily, converting a string to-and-from an array can be easily accomplished with split() and join() respectively:

  • String.split( "" ) - String to character array.
  • Array.join( "" ) - Character array to string.

Ok, let's take a look at some code. In the following demo, I am updating the core String prototype. That means that our splice() method will be available to all string instances, now and in the future (since they all extend the same String.prototype object):

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Creating A String.splice() Method In Javascript</title>
  •  
  • <script type="text/javascript">
  •  
  •  
  • // Extend the String prototype to include a splice method.
  • // This will use an Array-based splitting / joining approach
  • // internally.
  • String.prototype.splice = function(
  • index,
  • howManyToDelete,
  • stringToInsert /* [, ... N-1, N] */
  • ){
  •  
  • // Create a character array out of the current string
  • // by splitting it. In the context of this prototype
  • // method, THIS refers to the current string value
  • // being spliced.
  • var characterArray = this.split( "" );
  •  
  • // Now, let's splice the given strings (stringToInsert)
  • // into this character array. It won't matter that we
  • // are mix-n-matching character data and string data as
  • // it will utlimately be joined back into one value.
  • //
  • // NOTE: Because splice() mutates the actual array (and
  • // returns the removed values), we need to apply it to
  • // an existing array to which we have an existing
  • // reference.
  • Array.prototype.splice.apply(
  • characterArray,
  • arguments
  • );
  •  
  • // To return the new string, join the character array
  • // back into a single string value.
  • return(
  • characterArray.join( "" )
  • );
  •  
  • };
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // Create our test string value.
  • var message = "Katie is sort of cool.";
  •  
  • // Set the part of the string that we want to delete.
  • var lameStuff = "sort of cool";
  •  
  • // Now, let's create a more endearing message.
  • var betterMessage = message.splice(
  • message.indexOf( lameStuff ),
  • lameStuff.length,
  • "crazy-insane kinds of hot"
  • );
  •  
  • // Output the new message.
  • console.log(
  • "New message:",
  • betterMessage
  • );
  •  
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Intentionally left blank. -->
  • </body>
  • </html>

As you can see, the workflow is actually quite simple:

  1. Convert string to character array.
  2. Perform array-based splicing.
  3. Convert character array back to string.

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

New message: Katie is crazy-insane kinds of hot.

As you can see, the existing substring "sort of cool" was deleted and the new substring "crazy-insane kinds of hot" was inserted. While this operation is being executed, our base data structure becomes an array of character values. And yet, the value we are inserting is a string; this mixing of "data types" doesn't matter because when we join() the array of characters back together, it all gets flattened into one string value.

NOTE: I use "data types" here in the losest sense. Javascript doesn't actually differentiate between strings and characters (a character is a sting of length one).

While this was fun to do, I can't think of a great use-case for a string-based splice() method. Typically, when I am replacing one string into (or out of) another string, it's through the use of Javascript's regular express replace method. Even so, this exploration definitely brings to light some of the power that is affording through the use of Prototypal inheritance mechanisms.




Reader Comments

Mar 29, 2011 at 1:59 PM // reply »
2 Comments

nice article ben! any time you're augmenting the built-ins, it's a good idea to at least check for the presence of the property before adding it, something like:

  • if ( !("splice" in String.prototype) ) {
  • String.prototype.splice = function() {
  • // implementation of new method
  • }
  • }

or you can always try to default to the native's existing property (if you're polyfilling, for example with Array.forEach or Object.keys),thereby only creating it if necessary

String.prototype.splice = String.prototype.splice || function() {
// implementation of new method
}

as always, keep up the good work!


Mar 29, 2011 at 10:04 PM // reply »
11,246 Comments

@Keegan,

Ah, good call! And, while I know that Javascript is mostly consistent, there are some cross-browser inconsistency for some of the newer syntax items. In such a case, especially, you have to be checking to see if a method already exists.

Excellent catch!


Apr 3, 2011 at 1:03 PM // reply »
272 Comments

@Ben, totally tangential: Just watched the movie Splice. Similar topic to an otherwise-stale genre (The Host, Mimic, Species, etc), but with a critter that can be as lovable as Gizmo.


Apr 3, 2011 at 1:06 PM // reply »
11,246 Comments

@WebManWalking,

I've seen Splice. I actually really liked it. I have to admit, it was kind of a "hot" movie - though the ending was a bit strange. My friend wanted to take her kids to see it; I advised against it :)


Apr 3, 2011 at 2:21 PM // reply »
272 Comments

If you mean what I think you mean about "a bit strange", that was foreshadowed twice. Not that foreshadowing made it any less strange. Without giving away any spoilers, I think they must've started with the some of same genetic material as Ginger.

Anyway, it's currently showing on Cinemax if your friend wants to watch it without her kids. Here are some trailers:

http://www.splicethefilm.com/dvd/


Apr 3, 2011 at 2:22 PM // reply »
272 Comments

Oh, and I liked it to. Inventive.


Apr 3, 2011 at 6:20 PM // reply »
11,246 Comments

@WebManWalking,

Yeah, it was definitely foreshadowed with those slug creatures (or whatever the heck they were).


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