Using Slice(), Substring(), And Substr() In Javascript

Posted March 28, 2011 at 10:34 AM by Ben Nadel

Tags: Javascript / DHTML

In the book, Eloquent Javascript: A Modern Introduction to Programming, Marijn Haverbeke takes the reader through a good number of string-parsing examples. And, in his examples, Haverbeke makes frequent use of the String method, slice(). When I think of slice(), I think of extracting portions of a Javascript array; I don't think I was even aware that the Javascript String prototype had a slice() method. To clear up my own confusion and misconceptions, I wanted to take a quick look at the various ways in which Javascript allows for partial string extraction.

From what I can see, there are three primary methods for substring extraction:

  • String.slice( begin [, end ] )
  • String.substring( from [, to ] )
  • String.substr( start [, length ] )

In all cases, the second argument is optional. If it is not provided, the substring will consist of the start index all the way through the end of the string. For both the slice() and substring() methods, the second argument is exclusive; that is, the resultant substring will not contain the character at the final index.

Let's take a look as these three approaches in action:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Extracting Substrings In Javascript</title>
  •  
  • <script type="text/javascript">
  •  
  •  
  • // For these demos, let's create a numbered string so that
  • // we can easily see where the indexes come into play with
  • // all of the substring methods.
  • //
  • // NOTE: We are starting at zero since Javascript is all
  • // zero-based.
  • var numbers = "0123456789";
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // String.slice( begin, end )
  •  
  • // Let's start by using both begin and end.
  • console.log(
  • "slice( 3, 7 ) :",
  • numbers.slice( 3, 7 )
  • );
  •  
  • // What happens when we start with a negative number.
  • console.log(
  • "slice( -7, 7 ) :",
  • numbers.slice( -7, 7 )
  • );
  •  
  • // What happens when we use two negative numbers.
  • console.log(
  • "slice( -7, -3 ) :",
  • numbers.slice( -7, -3 )
  • );
  •  
  • // What happens when we omit the last argument.
  • console.log(
  • "slice( 3 ) :",
  • numbers.slice( 3 )
  • );
  •  
  • // And with the negative, end-relevant index.
  • console.log(
  • "slice( -7 ) :",
  • numbers.slice( -7 )
  • );
  •  
  • // If the index is out of range, it returns the empty string.
  • console.log(
  • "slice( 100, 101 ) :",
  • numbers.slice( 100, 101 )
  • );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // String.substring( from, to )
  •  
  • // Let's start by using both begin and end.
  • console.log(
  • "substring( 3, 7 ) :",
  • numbers.substring( 3, 7 )
  • );
  •  
  • // What happens when we start with a negative number.
  • console.log(
  • "substring( -7, 7 ) :",
  • numbers.substring( -7, 7 )
  • );
  •  
  • // What happens when we use two negative numbers.
  • console.log(
  • "substring( -7, -3 ) :",
  • numbers.substring( -7, -3 )
  • );
  •  
  • // What happens when we omit the last argument.
  • console.log(
  • "substring( 3 ) :",
  • numbers.substring( 3 )
  • );
  •  
  • // And with the negative, end-relevant index.
  • console.log(
  • "substring( -7 ) :",
  • numbers.substring( -7 )
  • );
  •  
  • // If the index is out of range, it returns the empty string.
  • console.log(
  • "substring( 100, 101 ) :",
  • numbers.substring( 100, 101 )
  • );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // String.substr( start, length )
  •  
  • // Let's start by using both start and length
  • console.log(
  • "substr( 3, 4 ) :",
  • numbers.substr( 3, 4 )
  • );
  •  
  • // What happens when we start with a negative number.
  • console.log(
  • "substr( -7, 4 ) :",
  • numbers.substr( -7, 4 )
  • );
  •  
  • // What happens when we omit the last argument.
  • console.log(
  • "substr( 3 ) :",
  • numbers.substr( 3 )
  • );
  •  
  • // And with the negative, end-relevant index.
  • console.log(
  • "substr( -7 ) :",
  • numbers.substr( -7 )
  • );
  •  
  • // If the index is out of range, it returns the empty string.
  • console.log(
  • "substr( 100, 1 ) :",
  • numbers.substr( 100, 1 )
  • );
  •  
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Intentionally left blank. -->
  • </body>
  • </html>

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

slice( 3, 7 ) : 3456
slice( -7, 7 ) : 3456
slice( -7, -3 ) : 3456
slice( 3 ) : 3456789
slice( -7 ) : 3456789
slice( 100, 101 ) :

substring( 3, 7 ) : 3456
substring( -7, 7 ) : 0123456
substring( -7, -3 ) :
substring( 3 ) : 3456789
substring( -7 ) : 0123456789
substring( 100, 101 ) :

substr( 3, 4 ) : 3456
substr( -7, 4 ) : 3456
substr( 3 ) : 3456789
substr( -7 ) : 3456789
substr( 100, 1 ) :

As you can see, the slice() and substring() methods are roughly the same; the only difference is that the slice() method can accept a negative index, relative to the end of the string. Should you try to use a negative index in substring(), it seems to be relative the beginning of the string (and therefore is out-of-bounds).

The substr() method can use a negative index; but, rather than using a to-argument, it uses a length-argument. This can be especially useful if you know the length of the substring ahead of time and don't want to perform any superflous math to calculate the necessary indices.

NOTE: According to W3Schools, using a negative index in substr() does not work with Internet Explorer (IE).

I can't see a reason to use the substring() method. It appears to be a less-robust version of the slice() method. If you know the indices, use slice(); if you know the length, use substr(). Unless I'm missing something subtle, the decision making seems to be fairly straightforward.




Reader Comments

Mar 28, 2011 at 11:13 AM // reply »
6 Comments

I'm with you -- I never even noticed the string slice() method before for some reason. Thanks for pointing it out! I've always just used the substring method, but the ability to use negative indexes could definitely come in handy.

There are probably cases where you might want any negative number to just be treated the same as 0, so the substring method could still be useful, though I don't have a particular use case in mind.


Mar 28, 2011 at 11:52 AM // reply »
22 Comments

It makes sense when you think that you can inspect a JS array and see a string representation of it.


Mar 28, 2011 at 2:29 PM // reply »
3 Comments

This is good information. I was mistakenly using substring since it was named the same as other languages but since I was expecting the behavior from substr I had to perform a calculation to pass the correct arguments. Thanks for this!


Mar 28, 2011 at 9:15 PM // reply »
10,743 Comments

@David,

The negative offset is definitely a cool concept. I see some languages support that for array-addressing as well. I've not had the chance to play with it too much (as ColdFusion doesn't have this concept); but, I am sure it can be very useful for the last element (-1).

@Andy,

Good point - and I think other languages truly treat strings as arrays of characters at the core.

@Rob,

No problem - yeah, using length is typically easier than having to determine the appropriate the end index. Glad to help!


Apr 15, 2011 at 3:22 PM // reply »
9 Comments

Daniel's response here lists a few more differences:

http://stackoverflow.com/questions/2243824/what-is-the-difference-between-string-slice-and-string-substring-in-javascript


Apr 27, 2011 at 9:00 AM // reply »
2 Comments

I think in this topic, we have to consider the split() function also. The split() method,
breaks the string where the separator(delimiter) occurs and returns the new strings in an array.

syntax: string.split(separator, limit)

example:

<script type="text/javascript">

var newstring = "abcdefg";
var cutstring = newstring.split("d");

</script>

Here the output of cutstring[0] will be abc and cutstring[1] will be efg. d is the delimiter here and so it won't appear in our output. Please note that limit is an optional one(integer) an it specifies the number of splits.


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
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 21, 2012 at 1:58 AM
Updated: Converting A ColdFusion Query To CSV Using QueryToCSV()
Hi Ben, why do you need to have so many double quotes when adding the field and field name to the row data? ----------------------------------------- <cfset LOCAL.RowData[ LOCAL.ColumnIndex ] = ... read »
AXL
May 21, 2012 at 1:24 AM
URL Rewriting And ColdFusion's WriteToBrowser Image Functionality (CFFileServlet)
@Mounir, Open your lower case URL Rewrite rule and add the following condition. Condition input: {REQUEST_URI} Check if input string: Does Not Match the Pattern Pattern: ^/CFFileServlet/_cf_ca ... read »
May 20, 2012 at 4:28 AM
Understanding The Complex And Circular Relationships Between Objects In JavaScript
@Will Vaughn I tried your javascript example but got this error:- foo.print is not a function ... read »
May 19, 2012 at 5:37 AM
A Graphical Explanation Of Javascript Closures In A jQuery Context
Thanks for this article, but I fear you missed an important point. If variables in the outer context change, these changes affect the inner anonymous functions as well. That means: if you change the ... read »
May 18, 2012 at 3:39 PM
Parsing CSV Data With An Input Stream And A Finite State Machine
Can you use file upload button with this? and read live? or does the file have to already be on the server saved? ... read »
May 18, 2012 at 1:06 AM
VIRGO (Aug. 23-Sept. 22): Dead On The Money!
A friend of mine and I were arguing about astrology and she told me that he believes in astrology. She hasn't provided me with any evidence that the belief makes any sense to me. She she been telling ... read »
May 17, 2012 at 11:32 PM
Using ColdFusion to Handle 404 Errors (Page Not Found) On Development Server
Very easy the configuration. I read a lot pages and I can't find the solution. I open the administrator and change this Administrator/server settings/Error Handlers/Missing Template Handler and p ... read »
May 17, 2012 at 3:13 PM
LOCAL Variables Scope Conflicts With ColdFusion Query of Queries
I never cease to be amazed that almost EVERY random CF issue I come across lands me on your site. Thank you for documenting your findings for the world. ... read »