Chapter 1. Working with JavaScript Strings
1.0. Introduction
JavaScript strings are the most important component of JavaScript, probably used more than any other data type. Though you may get numeric values from web page forms, the values are retrieved as strings, which you then have to convert into numeric values.
Strings are also used as parameters when invoking server-side
application calls through Ajax, as well as forming the basic serialization
format of every JavaScript object. One of the methods that all JavaScript
objects share is toString
, which returns a
string containing the serialized format of the object.
A String Primitive
A JavaScript string can be both a primitive data type or an object. As
a primitive type, it joins with four other JavaScript primitive types:
number, Boolean (true or false), null
(no value), and undefined
(unknown).
In addition, as a primitive data type, strings are also JavaScript
literals: a collection that includes
numbers (as either floating point or integer), the literal format for
arrays, objects, and regular expressions, as well as numbers and
Booleans.
Note
We’ll see more about the literal formats for the various JavaScript objects throughout the book.
A string is zero or more characters delimited by quotes, either single quotes:
'This is a string'
Or double quotes:
"This is a string"
There is no rule for which type of quote to use. If you’re including single quotes within the text, you’ll most likely want to use double quotes:
"This isn't a number."
If you mix up the quote types—begin a string with a single quote and end with a double—you’ll receive an application error:
var badString = 'This is a bad string"; // oops, error
Both quote types are used interchangeably in the book.
A String Object
A string object is called String
,
appropriately enough, and like all other JavaScript objects has a set of
properties that come prebuilt into the object type.
A String
object can be
instantiated using the JavaScript new
operator, to create a new object instance:
var city = new String("St. Louis");
Once instantiated, any one of the available string properties can
be accessed on it, such as in the following code, where the string is
lowercased using the String
object
method toLowerCase
:
var lcCity = city.toLowerCase(); // new string is now st. louis
If you access the String
constructor without using new
, you’ll
create a string literal rather than a String
object:
var city = String("St. Louis");
If you do need to access a String
object method on a string literal, you
can. What happens is the JavaScript engine creates a String
object, wraps it around the string
literal, performs the method call, and then discards the String
object.
When to use String
, as compared
to using a string literal, depends on the circumstances. Unless you plan
on using the String
object
properties, you’ll want to use string literals wherever possible.
However, if you’ll be using String
methods, then create the string as an object.
See Also
Mozilla has a terrific page that discusses the concept of JavaScript literals and the different types. You can access the page at https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Literals.
1.1. Concatenating Two or More Strings
Solution
Concatenate the strings using the addition (+
) operator:
var string1 = "This is a "; var string2 = "test"; var string3 = string1 + string2; // creates a new string with "This is a test"
Discussion
The addition operator (+
) is typically used to
add numbers together:
var newValue = 1 + 3; // result is 4
In JavaScript, though, the addition operator is overloaded, which means it can be used for multiple data types, including strings. When used with strings, the results are concatenated, with the strings later in the equation appended to the end of the string result.
You can add two strings:
var string3 = string1 + string2;
or you can add multiple strings:
var string1 = "This"; var string2 = "is"; var string3 = "a"; var string4 = "test"; var stringResult = string1 + " " + string2 + " " + string3 + " " + string4; // result is "This is a test"
There is a shortcut to concatenating strings, and that’s the
JavaScript shorthand assignment operator
(+=
). The following code snippet, which uses this
operator:
var oldValue = "apples"; oldValue += " and oranges"; // string now has "apples and oranges"
is equivalent to:
var oldValue = "apples"; oldValue = oldValue + " and oranges";
The shorthand assignment operator works with strings by concatenating the string on the right side of the operator to the end of the string on the left.
There is a built-in String
method that can concatenate multiple strings: concat
. It takes one or more string
parameters, each of which are appended to the end of the string
object:
var nwStrng = "".concat("This ","is ","a ","string"); // returns "This is a string"
The concat
method can be a
simpler way to generate a string from multiple values, such as
generating a string from several form fields. However, the use of the
addition operator is the more commonly used approach.
1.2. Concatenating a String and Another Data Type
Solution
Use the exact same operators, such as addition
(+
) and shorthand assignment (+=
),
you use when concatenating strings:
var numValue = 23.45; var total = "And the total is " + numValue; // string has "And the total is 23.45"
Discussion
A different process occurs when adding a string and another data type. In the case of another data type, such as a Boolean or number, the JavaScript engine first converts the other data type’s value into a string, and then performs concatenation:
// add a boolean to a string var boolValue = true; var strngValue = "The value is " + boolValue; // results in "The value is true" // add a number to a string var numValue = 3.0; strngValue = "The value is " + numValue; // results in "The value is 3"
The automatic data conversion also applies if you’re concatenating
a String
object with a string
literal, which is a necessary capability if you’re not sure whether the
strings you’re working with are objects or literals but you still want
to create a concatenated string:
var strObject = new String("The value is "); var strngLiteral = "a string"; var strngValue = strObject + strngLiteral; // results in "The value is a string"
The resulting string is a string literal, not a String
object.
1.3. Conditionally Comparing Strings
Solution
Use the equality operator
(==
) within a conditional test:
var strName = prompt("What's your name?", ""); if (strName == "Shelley") { alert("Your name is Shelley! Good for you!"); } else { alert("Your name isn't Shelley. Bummer."); }
Discussion
Two strings can be compared using the equality operator
(==
). When used within a conditional statement, a
block of code is run if the test evaluates to true (the strings are
equal):
if (strName == "Shelley") { alert("Your name is Shelley! Good for you!"); }
If the strings are not equal, the first statement following the
conditional statement block is processed. If an
if...else conditional statement is used, the block
of code following the else
keyword is
the one that’s processed:
if (strName == "Shelley") { alert("Your name is Shelley! Good for you!"); } else { alert("Your name isn't Shelley. Bummer."); }
There are factors that can influence the success of the string
comparison. For instance, strings have case, and can consist of uppercase
characters, lowercase characters, or a combination of both. Unless case
is an issue, you’ll most likely want to convert the string to all
lowercase or uppercase, using the built-in String
methods toLowerCase
and
toUpperCase
, before making the
comparison, as shown in the following code:
var strName = prompt("What's your name?", ""); if (strName.toUpperCase () == "SHELLEY") { alert("Your name is Shelley! Good for you!"); } else { alert("Your name isn't Shelley. Bummer."); }
Note that the toUpperCase
method (and toLowerCase
) do not take
any parameters.
In Recipe 1.2, I
discussed that data type conversion occurs automatically when
concatenating a numeric or Boolean value, or a String
object to a string. This same type of
data type conversion also occurs with the equality operator if one value
is a string. In the following, the number 10.00 is converted into the
string “10”, and then used in the comparison:
var numVal = 10.00; if (numVal == "10") alert ("The value is ten"); succeeds
There may be times, though, when you don’t want automatic data
conversion to occur—when you want
the comparison to fail if the values are of different data types. For
instance, if one value is a string literal and the other is a String
object, you might want the comparison
to fail because the two variables are of different data types,
regardless of their perspective values. In this case, you’ll want to use
a different equality operator, the strict equality operator
(===
):
var strObject = new String("Shelley"); var strLiteral = "Shelley"; if (strObject == strLiteral) // this comparison succeeds ... if (strObject === strLiteral) // fails because of different data types
The comparison fails if the two variables being compared are different data types, even though their primitive string values are the same.
Sometimes, you might want to specifically test that two strings
are not alike, rather than whether they are alike.
The operators to use then are the inequality operator
(!=
) and strict inequality operator
(!==
). They work in the same manner as the previous
two operators just discussed, but return true when the strings are not
alike:
var strnOne = "one"; var strnTwo = "two"; if (strnOne != strnTwo) // true, as they are not the same string value
The strict inequality operator returns true if the strings are not the same value or the data type of the two operands (values on either side of the operator) is different:
var strObject = new String("Shelley"); var strLiteral = "Shelley"; if (strObject !== strLiteral) // succeeds, because data type of operands differs
If you’re more interested in discovering how two strings may differ, you can use other comparison operators, as shown in Table 1-1.
Comparison operators work numerically with numbers, but lexically with strings. For instance, the value “dog” would be lexically greater than “cat”, because the letter “d” in “dog” occurs later in the alphabet than the letter “c” in “cat”:
var sOne = "cat"; var sTwo = "dog" if (sOne > sTwo // false, because "cat" is lexically less than "dog"
If two string literals only vary based on case, the uppercase characters are lexically greater than the lowercase letter:
var sOne = "Cat"; var sTwo = "cat"; if (sOne >= sTwo) // true, because 'C' is lexically greater than 'c'
There is no strict greater than or strict less than operators, so it makes no difference if the data type of the operands differs:
var sOne = new String("cat"); var sTwo = "cat"; if (sOne <= sTwo) // both equal, so true, as data type doesn't matter
Before leaving this recipe, there is another approach you can use
to compare strings, but this one has a little kick to it. It’s based on
the String method, localeCompare
.
The localeCompare
method
takes one parameter, a string, which is compared against the string
value to which it is attached. The method returns a numeric value equal
to 0 if the two strings are the same; –1 if the string parameter is
lexically greater than the original string; 1 otherwise:
var fruit1 = "apple"; var fruit2 = "grape"; var i = fruit1.localeCompare(fruit2); // returns -1
For the most part, you’ll probably use the comparison operators
rather than the locale
Compare
method, but it’s always interesting to see more than one
approach.
See Also
For more on string-to-number conversion, see Recipe 4.5.
1.4. Finding a Substring in a String
Solution
Use the String
object’s
built-in indexOf
method to find the position of the substring, if it
exists:
var testValue = "This is the Cookbook's test string"; var subsValue = "Cookbook"; var iValue = testValue.indexOf(subsValue); // returns value of 12, index of substring if (iValue != -1) // succeeds, because substring exists
Discussion
The String indexOf
method
returns a number representing the index, or
position of the first character of the substring, with 0 being the index
position of the first character in the string.
To test if the substring doesn’t exist, you can compare the returned value to –1, which is the value returned if the substring isn’t found:
if (iValue != -1) // true if substring found
The indexOf
method takes two
parameters: the substring, and an optional second parameter, an index
value of where to begin a search:
var tstString = "This apple is my apple"; var iValue = tstString.indexOf("apple", 10); // returns 17, index of second substring
The indexOf
method works from
left to right, but sometimes you might want to find the index of a
substring by searching within the string from right to left. There’s
another String
method, lastIndexOf
, which
returns the index position of the last occurrence of a substring within
a string:
var txtString = "This apple is my apple"; var iValue = tstString.lastIndexOf("apple"); // returns 17, // index of last occurrence of substring
Like indexOf
, lastIndexOf
also takes an optional second
parameter, which is an index value of where to start the search, counted
from the right:
"This apple is my apple".lastIndexOf("apple"); // returns value of 17 "This apple is my apple".lastIndexOf("apple",12); // returns value of 5 "This apple is my apple".lastIndexOf("apple", 3); // returns value of -1, not found
Notice that the value returned from lastIndexOf
changes based on the starting
position, as counted from the string’s right.
See Also
The String
method search
is used with regular expressions in
order to find a specific pattern within a string, and is discussed in
Recipe 2.3. The String
method replace
can be used to replace a substring
found using a regular expression, and is discussed in Recipe 2.4.
1.5. Extracting a Substring from a String
Problem
You have a string with several sentences, one of which has a list of items. The list begins with a colon (:) and ends with a period (.). You want to extract just the list.
Solution
Use the indexOf String
method
to locate the colon, and then use it again to find the first period
following the colon. With these two locations, extract the string using
the String
substring
method:
var sentence = "This is one sentence. This is a sentence with a list of items: cherries, oranges, apples, bananas."; var start = sentence.indexOf(":"); var end = sentence.indexOf(".", start+1); var list = sentence.substring(start+1, end);
Discussion
The list is delimited by a beginning colon character and an ending
period. The indexOf
method is used
without the second parameter in the first search, to find the colon. The
method is used again, but the colon’s position (plus 1) is used to
modify the beginning location of the search for the period:
var end = sentence.indexOf(".",start+1);
If we didn’t modify the search for the ending period, we would have ended up with the location of the first sentence’s period, rather than the location of the second sentence’s period.
Once we have the beginning and ending location for the list, we
use the substring
method, passing in
the two index values representing the beginning and ending positions of
the string:
var list = sentence.substring(start+1, end);
The resulting string in list is:
cherries, oranges, apples, bananas
We could then use a method, such as String.split
to split the list into its individual values:
var fruits = list.split(",") ; // array of values
There is another string extraction method, substr
, but it’s based on the index position
of the start of the substring, and then passing in the length of the
substring as the second parameter. In a real life application, we won’t
know the length of the sentence.
See Also
See Recipe 1.7 for
more on using the String.split
method.
1.6. Checking for an Existing, Nonempty String
Solution
Use a combination of the typeof
operator, the
general valueOf
method (which all
JavaScript objects share), and the String
length
property to create a conditional test that ensures a
variable is set, is a string, and is not empty:
// true if variable exists, is a string, and has a length greater than zero if(((typeof unknownVariable != "undefined") && (typeof unknownVariable.valueOf() == "string")) && (unknownVariable.length > 0)) { ... }
Discussion
Probably the most important built-in property for String
is length
. You can use length
to find out how long the string is, and
to test whether the string variable is an empty
string (zero length) or not:
if (strFromFormElement.length == 0) // testing for empty string
However, when you’re working with strings and aren’t sure whether
they’re set, you can’t just check their length, as you’ll get an
undefined JavaScript error if the variable has never been set. You have
to combine the length test with another test for existence, and this
brings us to the typeof
operator.
The JavaScript typeof
operator returns the type of a variable. The list of
possible returned values are:
"number"
if variable is a number"string"
if variable is a string"boolean"
if variable is a Boolean"function"
if variable is a function"object"
if variable is null, an array, or another JavaScript object"undefined"
if variable is undefined
The last value is what interests us right now, because a variable
that has never been defined has a data type of undefined
.
When a data type test is combined with a test of string length via
a logical AND
(&&
) operator, the only time the entire
statement will succeed is if the variable has been defined,
and it contains a string with a length longer than
zero:
// succeeds if variable exists, and has length greater than zero if ((typeof unknownVariable !== "undefined") && (unknownVariable.length > )) { ... }
If the first test fails—whether the variable has been defined—the second condition isn’t processed, as the entire statement fails. This prevents the error of accessing a property on an undefined variable.
The conditional statement in the last code snippet works, but what
happens if the variable is defined, but is not a string? For instance,
if the variable is a number? Well, in this case, the condition still
fails, because the length
property is undefined for a
number. However, what if the value is a String
object?
If you’re not sure what type the variable is, you can also
explicitly test for the "string"
data
type before testing the length:
// succeeds if string with length greater than zero if ((typeof unknownVariable == "string") && (unknownVariable.length > 0)) { ... }
If the test succeeds, you know exactly what you have: a string,
with a length greater than zero. However, if the variable is a String
object, not a literal, typeof
returns a data type of "object"
not "string"
. That’s why the solution incorporates
another JavaScript object method, valueOf
.
The valueOf
method is available for all JavaScript objects, and
returns the primitive value of whatever the object is: for Number
, String
, and boolean
, their primitive values; for Function
, the function text, and so on. So if
the variable is a String
object,
valueOf
returns
a string literal. If the variable is already a string literal, applying
the valueOf
method to it temporarily
wraps it in a String
object, which
means the valueOf
method will still return a string
literal.
Our conditional test then ends up incorporating a test to see if
the variable has been set, and if so, whether it is a String
object or literal using valueOf
, and, finally, whether the length of
the string is greater than zero:
// true if variable exists, is a string, and has a length greater than zero if(((typeof unknownVariable != "undefined") && (typeof unknownVariable.valueOf() == "string")) && (unknownVariable.length > 0)) { ... }
Seems like a lot of work, but typically your application won’t have to be this extensive when testing a value. Generally you’ll only need to test whether a variable has been set, or find the length of a string, in order to ensure it’s not an empty string.
1.7. Breaking a Keyword String into Separate Keywords
Problem
You have a string with keywords, separated by commas. You want to break the string into an array of separate keywords, and then print the keywords out with a keyword label.
Solution
Use the String split
method to split the string on the commas. Loop through the
array, printing out the separate values. Example 1-1 shows a complete
web page demonstrating this approach. The keywords are provided by the
web page reader, via a prompt window, and are then processed and printed
out to the web page.
<!DOCTYPE html> <head> <title>Example 1-1</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <script type="text/javascript"> window.onload = function() { // get keyword list var keywordList = prompt("Enter keywords, separated by commas",""); // use split to create array of keywords var arrayList = keywordList.split(","); // build result HTML var resultString = ""; for (var i = 0; i < arrayList.length; i++) { resultString+="keyword: " + arrayList[i] + "<br />"; } // print out to page var blk = document.getElementById("result"); blk.innerHTML = resultString; } </script> </head> <body> <div id="result"> </div> </body> </html>
Discussion
The String split
method takes
two parameters: a required parameter with the character representing the
separator for the split method; the second parameter (optional) is a
number representing a count of the number of splits to make. In Example 1-1, the separator is
a comma (,), and no second parameter is provided. An example of using
the second parameter is the following:
var strList = "keyword1,keyword2,keyword3,keyword4";
The following split
method call would generate
an array with two entries:
var arrayList = strList.split(",",2); // results in two element array
Not specifying the second parameter will split on every occurrence of the separator found:
var arrayList = strList.split(","); // results in four element array
Here’s an interesting use of split
: if you want to split a string on every
character, specify the empty string (''
) or
(""
) as the separator:
var arrayList = strList.split("");
You can also use a regular expression as the parameter to split, though this can be a little tricky. For instance, to find the same sentence list as returned from the example code in the solution, you could use a couple of regular expressions:
var sentence = "This is one sentence. This is a sentence with a list of items: cherries, oranges, apples, bananas."; var val = sentence.split(/:/); alert(val[1].split(/\./)[0]);
The regular expression looks for a colon first, which is then used for the first split. The second split uses a regular expression on the resulting value from the first split, to look for the period. The list is then in the first array element of this result.
Tricky, and a little hard to get your head around, but using
regular expressions with split
could be a handy
option when nothing else works.
See Also
See Recipe 5.3 for a
discussion about creating a string from an array. See Recipe 11.1 about accessing a
page element with the document object, and Recipe 12.1 about using the
innerHTML
property. Chapter 2 provides coverage of regular
expressions. Recipe 2.6
covers using capturing parentheses and a regular expression to get the
same results as the solutions demonstrated in this recipe.
1.8. Inserting Special Characters
Solution
Use one of the escape sequences in the string. For
instance, to add the copyright symbol into a block of text to be added
to the page (shown in Figure 1-1), use the escape
sequence \u00A9
:
var resultString = "<p>This page \u00A9 Shelley Powers </p>"; // print out to page var blk = document.getElementById("result"); blk.innerHTML = resultString;
Discussion
The escape sequences in JavaScript all begin with the backslash character, (\). This character lets the application processing the string know that what follows is a sequence of characters that need special handling.
Table 1-2 lists the other escape sequences.
The last three escape sequences in Table 1-2 are patterns, where providing different numeric values will result in differing escape sequences. The copyright symbol in the solution is an example of the Unicode sequence.
All of the escape sequences listed in Table 1-2 can also be represented as a Unicode
sequence. For instance, the horizontal tab (\t
), can
also be represented as the Unicode escape sequence, \u0009
. Of course, if the user agent
disregards the special character, as browsers do with the horizontal
tab, the use is moot.
One of the most common uses of escape sequences is to include double or single quotes within strings delimited by the same character:
var newString = 'You can\'t use single quotes in a string surrounded by single quotes';
1.9. Processing Individual Lines of a textarea
Solution
Use the String split
method,
combined with the line break escape sequence (\n
) to split the contents of the textarea
into its separate lines:
var txtBox = document.getElementById("inputbox"); var lines = txtBox.value.split("\n"); // print out last line to page var blk = document.getElementById("result"); blk.innerHTML = lines[lines.length-1];
Discussion
Escape sequences can be used for more than building strings; they
can also be used in pattern-matching operations. In the solution, the
textarea
string is split into its
separate lines by looking for the escape sequence for the newline
character (\n
).
This approach is also a way to convert text that may be encoded
with escape sequences, such as the newline character, into properly
formatted HTML. For instance, to modify the example to output the
textarea
exactly as typed, but as
HTML, use the following:
// get textarea string and split on new lines var txtBo x = document.getElementById("test"); var lines = txtBox.value.split("\n"); // generate HTML version of text var resultString = "<p>"; for (var i = 0; i < lines.length; i++) { resultString += lines[i] + "<br />"; } resultString += "</p>"; // print out to page var blk = document.getElementById("result"); blk.innerHTML = resultString;
This code snippet converts all line breaks into the HTML br
element. When added back to the page, the
text is printed as it was found in the textarea
, line breaks and all. This is a
popular technique used to echo comments, as they are typed for a live
preview, in many blogs.
See Also
Another approach to replacing characters in a string is to use a
regular expression with the String
replace
method, covered in Recipe 2.5.
1.10. Trimming Whitespace from the Ends of a String
Solution
Use the new ECMAScript 5 String
trim
method:
var txtBox = document.getElementById("test"); var lines = txtBox.value.split("\n"); var resultString = ""; for (var i = 0; i < lines.length; i++) { var strng = lines[i].trim(); resultString += strng + "-"; } alert(resultString);
Discussion
Prior to the release of ECMAScript 5, you had to use regular
expressions and the String replace
method to trim the unwanted whitespace from around a string. Now,
trimming a string is as simple as calling the trim
method.
Most, if not all, browsers will eventually support trim
. Among the target browsers for this book,
the only one that doesn’t is IE8. A workaround you can use is outlined
below, which not only allows for the use of trim
, but a fallback if trim does not
exist.
First, at some point before you need to use the trim
functionality, you must test to see if
trim
exists as a property of the
String
object. If it doesn’t, you’ll
need to use the String prototype
to add a customized trim
method to the object:
if (typeof String.trim == "undefined") { String.prototype.trim = function() { return this.replace(/(^\s*)|(\s*$)/g, ""); } }
Once this code is processed, when you call the trim
method on any string, it will return a
string with whitespace trimmed from both ends (as long as the
application is within page scope). This functionality happens regardless
of whether the method is already built-in by the browser, or added by
your hack:
var strng = lines[1].trim();
Note
Most of the JavaScript framework libraries, such as jQuery,
which I introduce in Chapter 17, have
already added the trim
method.
Other new, related methods from ECMAScript 5 are trimLeft
, which trims the whitespace on the
left side of the string, and trimRight
, which does the same on the right
side of the string.
See Also
The use of regular expressions is covered in Chapter 2. The use of the JavaScript object
prototype
property is covered in
Recipe 16.3.
1.11. Left- or Right-Pad a String
Solution
Test the length of the string, then generate a padding string
consisting of duplications of a given character to either concatenate to
the original string (if padding to the right) or attaching to the
beginning of the string (if padding to the left). The following
left-pads the existing string with the nonbreaking space named character (
):
<!DOCTYPE html> <head> <title>Recipe 1.12</title> </head> <body> <div id="result"></div> <script> var prefLineLength = 20; var oldStr = "This is a string"; var diff = prefLineLength - oldStr.length; var filler = ' '; for (var i = 0; i < diff; i++) { oldStr=filler + oldStr; } document.getElementById("result").innerHTML=oldStr; </script> </body>
Discussion
You don’t want to pad strings that go into a database, because you want to keep the data in the database as small and efficient as possible. But you might want to pad the value before you display it in the web page.
The characters you use to pad the string are guided by the use.
Typically, you’ll use spaces. However, if the value is inserted into a
web page that disregards multiple spaces, you’ll either have to use the
named entity (
) or its
numeric equivalent( 
) if
your content needs to be XHTML-compatible. Or you can just use CSS to
format the text positioning. For instance, to right-align the text,
create the CSS rule:
.rightformatted { text-align: right: }
And then apply the rule when you add the string to the page. You
can use the CSS rule as a class name with the innerHTML
property:
var div = document.getElementById("item"); item.innerHTML="<p>" + strValue + "</p>";
or you can use DOM (Document Object Model) Level 2 functionality:
var num = 123.55; var item = document.getElementById("item"); // create text node and paragraph element var txt = document.createTextNode(num); var p = document.createElement("p"); // attach text node to paragraph p.appendChild(txt); p.setAttribute("class","rightformatted"); // append paragraph to document element item.appendChild(p);
Get JavaScript Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.