The JavaScript objects are inherent components of the JavaScript language itself, and not the environment in which the JavaScript is processed. As such, theyâll always be available regardless of environment.
Among the basic JavaScript objects are those that parallel our data
types, which we discussed in Chapter 2: String
for strings, Boolean
for booleans, and of course, Number
for numbers. They
encapsulate the primitive types, providing additional functionality beyond
the basic conversion functionality we discussed in that chapter.
Three additional built-in objects provide necessary functionality
as well: Math
, Date
, and RegExp
. Math
and Date
are relatively self-explanatory;
they provide basic math and date functionality. If you havenât worked with
regular expressions before, RegExp
is the object that provides regular
expression functionality. Regular expressions are powerful though extremely
cryptic patterning capabilities that enable you to add very precise string
matching to applications.
JavaScript also has one built-in aggregator object, the Array
. All objects in JavaScript, in fact, are arrays, though we donât
typically treat the objects as arrays. Iâll discuss this in more detail
later in the chapter. First, though, weâll revisit the basic data type
objects introduced earlier, as we explore exactly what it means to be an
âobjectâ in JavaScript.
Iâll get into the details of JavaScriptâs object-oriented nature later in the book. For now, weâll look at the aspects of object-oriented functionality that are useful when working directly with the built-in JavaScript objects.
Objects in JavaScript have methods and other properties that you can
access using the object property operator, represented by a period
(.
). For instance, to find the length of a string associated with a String
object, you can access the objectâs
length
property:
var myName = "Shelley"; alert(myName.length);
You also access object functions, called methods, via the same property
operator, because methods are also
considered object properties. Here is an example of the String
objectâs strike
method, which encloses the stringâs text within HTML opening and
closing string element tags:
var myName = "Shelley"; alert(myName.strike()); // returns <strike>Shelley</strike>
This example might be somewhat confusing because it looks like Iâm
creating a string primitive rather than a String
object. In the code, the variable myName
is a string primitive variable,
true
. However, when a String
method is invoked on the variable, itâs
also an instance of a String
object,
with access to all of the String
properties, including length
and
strike
.
In Chapter 2, I mentioned how when an object method is invoked on a primitive data type, an object instance is created to wrap the primitive, the method call is processed, and then the object is discarded. The same principle applies to numbers and booleans as well.
However, instead of implicitly creating a String
,
Boolean
, or Number
object, you can explicitly create an object using the new
keyword and the following syntax:
var myName = new String("Shelley");
The new
keyword is important. If you omit it, youâll get a string primitive
rather than a string object. In other words, both of the following lines
of JavaScript create string primitives:
var strName = "Shelley"; var strName2 = String("Shelley");
Returning to the String
object,
once you create a String
object
instance, you can access the primitive value it wraps
(encloses) using another method that all the objects share, valueOf
:
var myName = new String("Shelley"); alert(myName.valueOf());
You can also access the primitive value directly, as though it were a primitive data type:
var myName = new String("Shelley"); alert(myName);
To repeat what I said earlier in Chapter 2, which technique to
useâstring primitive or String
object
instanceâdepends on how youâre using the variable. If youâre going to be
accessing the object properties, such as the String
objectâs length
and strike
methods, youâll want to create the
variable as an object. If you create a string primitive and then access it
like an object, JavaScript will convert the primitive to an object when
you access a String
property, but it
does so by converting the primitive to a temporary String
object, and then discarding the object
when itâs finished with the property. This isnât efficient.
var strName ="Shelley"; // string as primitive alert(strName.length); // String object is implicitly created, its data value set to strName, and length method processed
However, if youâre using a string (or a number or boolean) as a primitive, you donât need the object properties, and itâs more efficient just to use the string primitive technique of creating the variable:
var strName = "Shelley"; alert(strName);
Because weâre exploring object properties in this chapter, the examples in the rest of this chapter create variables as object instances.
Number
and String
object instances have their
own unique properties, whereas Boolean
does not. However, all three
inherit certain properties and methods from a higher-level object, which
Iâll cover in detail in Chapter 13. For now, among the
methods that all the objects inherit are toString
and valueOf
. As the Boolean
object has
only inherited properties, Iâll use this object type to demonstrate each
of these methods.
You actually can create an instance of a Boolean
object in several different ways,
depending on whether you want it
to be set to an initial value of false
or true
. If you create the object using empty
parentheses, the Boolean
is created
with a value of false
:
var boolFlag = new Boolean();
You can also use a number to set the initial value, such as 0 for
false
:
var boolFlag = new Boolean(0);
Or 1 for true
:
var boolFlag = new Boolean(1);
In addition, you can create and set the object using the literal
true
and false
:
var boolFlag1 = new Boolean(false); var boolFlag2 = new Boolean(true);
Whatâs interesting is that if you create the Boolean
instance with an empty string, the
object is set to an initial value of false
. However, if you create the Boolean
instance with any nonempty string, the
object is set to an initial value of true
:
var boolFlag1 = new Boolean(""); // set to false var boolFlag2 = new Boolean("false"); // set to true
Ignore what the string says in the second line in the code; the
string isnât empty, so the object instance is set to an initial value of
true
. You can test this for yourself
by using the valueOf
method, as
Example 4-1
demonstrates.
Example 4-1. Testing the value of a Boolean instance using the valueOf method
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Boolean valueOf</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function newBool() { var boolFlag = new Boolean("false"); alert(boolFlag.valueOf()); } //]]> </script> </head> <body onload="newBool()"> <p>Some page content</p> </body> </html>
Figure 4-1 shows
the alert window and the Boolean
instance value of true
when the page
is accessed in Opera. The valueOf
method returns the value of the primitive that the Boolean
(and Number
and String
) encapsulates.
The method toString
returns the
same value as valueOf
, except as a
string, "true"
, rather than true
:
var boolFlag = new Boolean("false"); var strFlag = boolFlag.toString(); // string containing "true"
Before getting into the Number
object, a note about instance versus object properties.
The two methods we used with the Boolean
object in the preceding section are
known as instance methods because the
methods are associated with the object instance, boolFlag
, rather than the object class,
Boolean
. Neither the toString
nor the valueOf
method would be very useful without
being attached to an instance, with its unique data to convert to a
string or be returned as a value.
Another type of object method is known as a static
method. Static methods donât operate on the instance data, but instead
are called directly on the object class. All of the Math
objectâs methods, which Iâll cover later
in the chapter, are static methods:
var newNum = Math.abs(oldNum);
The same instance versus object
implementation also applies to properties that arenât methods.
Specifically, five Number
properties
are accessible only via the Number
object itself. These are:
Typically, you use the infinity properties only to test when an
overflow condition has occurred. An overflow occurs
when a number is created that is either too small or too large, and
therefore exceeds the MIN_VALUE
or
MAX_VALUE
property:
var someValue = -1 * Number.MAX_VALUE * 2; alert(someValue); someValue = Number.MAX_VALUE * 2; alert(someValue);
The alert would display the value of -infinity
for NEGATIVE_INFINITY
first, followed by infinity
for POSITIVE_INFINITY
.
I use the Number
object in the
listing of the four properties to highlight the importance of accessing
these properties on the Number
object
itself, not on a Number
instance. If
you try to access these properties on a Number
instance, a value of undefined
will be returned:
var someNumber = new Number(3.0); var maxValue = someNumber.MAX_VALUE; // undefined
The Number
objectâs instance
methods have to do with conversionâto a string, to a locale-specific
string, to a given precision- or fixed-point representation, and to an
exponential notation. The Number
object has three instance
methods:
The global methods valueOf
and
toString
are also supported for Number
instances, as is an additional method,
toLocaleString
. The latter returns a
locale-specific version of the number. Unlike with Boolean
, the toString
method for the Number
object instance also takes one
parameter, a base, which you can use to convert the number between
decimal and hexadecimal, or between decimal and octal, and so on.
Example 4-2 demonstrates
the various Number
object instance
methods.
Example 4-2. The Number object instance methods
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Number methods</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function numbers() { // Number methods var newNumber = new Number(34.8896); document.writeln(newNumber.toExponential(3) + "<br />"); document.writeln(newNumber.toPrecision(3) + "<br />"); document.writeln(newNumber.toFixed(6) + "<br />"); var newValue = newNumber.valueOf(); document.writeln(newValue.toString(2) + "<br />"); document.writeln(newValue.toString(8) + "<br />"); document.writeln(newValue.toString(10) + "<br />"); document.writeln(newValue.toString(16) + "<br />"); } //]]> </script> </head> <body onload="numbers()"> <p>Some page content</p> </body> </html>
Figure 4-2 shows the results of running this JavaScript application in Safari.
The first method the code invokes is toExponential
, which the number of digits
appearing after the decimal point
passed in as a parameterâin this case, 3. The second method is toPrecision
, with a value of 3 also passed as
a parameter, representing the number of significant digits to include in
the string transformation. The third method the code called, toFixed
, is the number of digits to print out
after the decimalârounded if applicable.
The code then obtains the value of the Number
object using the valueOf
method and assigns this value to a new
variable before using the new variable with the toString
method calls. It does this because
toString
uses the base parameter only
if itâs used with an actual number, not an object. The variable newNumber
holds an object, not a number. Only
after we get the actual number and assign it to a second variable can we
use toString
with different base
representations.
The String
object is probably the most used of the built-in JavaScript
objects. You can explicitly create a new String
object using the new String
constructor, passing the literal
string as a parameter:
var sObject = new String("Sample string");
The String
object has several
methods, some associated with working with HTML and several not. Table 4-1 lists the properties and methods
available via String
object instances.
Table 4-1. String object methods
One of the non-HTML-specific methods, concat
, takes two strings and returns a result
with the second string concatenated onto the first. Example 4-3 demonstrates how
to create a String
object and use the
concat
method.
Example 4-3. Creating a String object and calling the concat method
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>String concatenation</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function stringConcat() { var sObj = new String(); var sTxt = sObj.concat("This is", " a ", "new string"); alert(sTxt); } //]]> </script> </head> <body onload="stringConcat()"> <p>Some page content</p> </body> </html>
There is no specified limit to the number of strings you can
concatenate with the String concat
method. However, I rarely use the concat
method; if Iâm going to be building a
string, I prefer using string primitives and the string
concatenation operator (+
) simply
because it is less cumbersome.
Of course, youâre going to want to minimize concatenation as much as possible. Each time you concatenate one string to another, youâre creating a new string object. Strings are immutable in JavaScript, which means you canât actually change a string once youâve created it. When you assign a new string value or modify an old value, youâre really just creating a new string which exists in memory, along with the old one, until the application goes out of scope (typically when the function is finished):
var newStr = "this is"; newStr+= " a new string"; // old string is discarded, new string is created
If you did a lot of concatenation, the performance of the application could suffer. However, most uses of string concatenation are simple variations of putting together a string with a few variable values, and you can use it without worrying much about performance.
The HTML formatting methodsâanchor
,
link
, big
,
blink
, bold
,
italics
, sub
,
sup
, small
, and strike
âgenerate strings that enclose the
String
object instanceâs literal
value within HTML element tags. Example 4-4 demonstrates how
these formatting methods work, using one specific string with different
methods.
Example 4-4. Working with the String objectâs formatting functions
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>String HTML</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function stringHTML() { var someString = new String("This is the test string"); document.writeln(someString.big() + "<br />"); document.writeln(someString.blink() + "<br />"); document.writeln(someString.sup() + "<br />"); document.writeln(someString.strike() + "<br />"); document.writeln(someString.bold() + "<br />"); document.writeln(someString.italics() + "<br />"); document.writeln(someString.small() + "<br />"); document.writeln(someString.link('http://www.oreilly.com')); } //]]> </script> </head> <body onload="stringHTML()"> <p>Some page content</p> </body> </html>
Figure 4-3 shows
the derived page opened in Firefox. Note the HTML styling added to each
variation of the string. What the image canât show is the blinking
action of the string formatted with blink
.
blink
is deprecated HTML,
which means that more modern HTML and XHTML specifications have
stopped supporting it, and eventually, browsers will stop supporting it
as well. It definitely wonât validate within a web page given a strict
Document Type Declaration (DOCTYPE), such as in Example 4-4. However, if you
use it with document.writeln
, the
page validates because the XHTML validators see the proper use of
JavaScript, not the generated results. If you copy the generated results
into a new document and run these with any XHTML validator, or try to
serve the pages as XHTML rather than HTML, youâll receive an error for
the use of blink
.
Warning
Even if you donât receive an error directly, you should avoid
using the HTML format methods (other than anchor
and link
) as much as possible, primarily because
they donât use the more modern Cascading Style Sheets (CSS) styling.
And whatever you do, avoid blink
:
itâs an obnoxious behavior.
Returning to the String
objectâs instance methods, the charAt
and charCodeAt
methods return the
character and the Unicode character code, respectively, at a given
location. The methods take one parameterâan index of the character to be
returned:
var sObj = new String("This is a test string"); var sTxt = sObj.charAt(3); document.writeln(sTxt);
The index values begin at zero; to return the character at the fourth position, pass in the value 3.
The substr
and substring
methods, as well as slice
, return a substring given two parameters, though whatâs returned and the
parameters differ among the three methods. The substr
method takes a starting index and the
length of the substring as parameters, whereas substring
extracts the characters between two
given indexes:
var sTxt = "This is a test string"; var ssTxt = sTxt.substr(5,8); // returns "is a tes" var ssTxt2 = sTxt.substring(5,8); // returns "is "
If the stop index is less than the start for substring
, the method swaps the two values. If
you omit the end parameter for both, the rest of the string after the
start index is returned. If the second index or length is longer than
the string, the length of the string is used.
The slice
method is similar to
substring
in that it takes two
indexes, but unlike substring
, if the stop index is less than
the start index, the values arenât swapped, and an empty string is
returned:
var ssTxt2 = sTxt.substring(4,1); // returns his var ssTxt3 = sTxt.slice(4,1); // returns empty string
As the code examples in this section demonstrate, you can use the
String
methods with a string literal,
as well as a String
object. Just as a
reminder: the application processing the JavaScript converts the
variable to an object, calls the method, and then reconverts the object
back to a primitive variable, discarding the object.
The indexOf
and lastIndexOf
methods return the index of a
search string, with the former returning the first occurrence and the
latter returning the last:
var sTxt = "This is a test string"; var iVal = sTxt.indexOf("t"); document.writeln(iVal);
Example 4-3
demonstrated concatenating strings together. If you want to do the
reverseâsplit a string apartâuse
the split
method. This method has two
parameters: the first is the character that marks each break; the
second, which is optional, is the number of splits to perform.
The JavaScript in Example 4-5 takes a string and splits it on the comma (,
)âperforming a break only on the first three
commas. The resultant values are then split on the equals sign (=
).
Example 4-5. Using the String split function to break a string into tokens
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Gotta Split</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function splitString() { var inputString = new String('firstName=Shelley,lastName=Powers,state=Missouri,statement="This is a test, of split"'); var arrayTokens = inputString.split(',',3); // process split on commas for (var i = 0; i < arrayTokens.length; i++) { document.writeln(arrayTokens[i] + "<br />"); // now split on equals and write just value var newTokens = arrayTokens[i].split('='); document.writeln(newTokens[1] + "<br /><br />"); } } //]]> </script> </head> <body onload="splitString()"> <p>Some page content</p> </body> </html>
The result of running this JavaScript application is the following output to the web page:
firstName=Shelley Shelley lastName=Powers Powers state=Missouri Missouri
This is a very handy way of processing form fields before theyâre submitted to the server, pulling in individual values from strings attached to the URL of the page, or a result returned from an Ajax call, which I demonstrate toward the end of the book.
Returning to the String
object
instance methods, toUpperCase
and
toLowerCase
, convert the string to
all upper- or lowercase characters, respectively, and return the
converted result:
var someString = new String("Mix of upper and lower"); var newString = someString.toUpperCase(); // uppercases all of the letters
These are particularly useful functions if case is going to be an issue because you can convert the string to all upper- or lowercase before processing.
There is also one static method on the String
objectâfromCharCode
:
var s = String.fromCharCode(345,99,99,76); document.writeln(s);
The fromCharCode
method
takes Unicode values separated by commas and returns a
string. However, as we discussed in Chapter 2, you can also embed
Unicode characters directly into a string.
The last String
methods depend
on a concept known as regular expressions. Because
regular expressions are associated with another built-in JavaScript
object, RegExp
, weâll look at all of
the regular-expression-related String
methods in the next section.
Regular expressions are arrangements of characters that form a pattern that you can then use against strings to find matches, make replacements, or locate specific substrings. Most programming languages support some form of regular expression, and JavaScript is no exception.
You can create a regular expression explicitly using the RegExp
object, although you can also create one
using a literal. The following uses the explicit option:
var searchPattern = new RegExp('s+');
The next line of code demonstrates the literal RegExp
option:
var searchPattern = /s+/;
In both cases, the plus sign (+
)
in the search pattern following the character s
matches
one or more consecutive uses of s
in a string. The
forward slashes with the literal (/s+/
) mark that the object being
created is a regular expression and not some other type of object.
The RegExp
object has only two unique instance methods of interest:
test
and exec
. The test
method determines whether a string passed
in as a parameter matches with the regular expression. The following
example tests the pattern /JavaScript
rules/
against the string to see
whether a match exists:
var re = /JavaScript rules/; var str = "JavaScript rules"; if (re.test(str)) document.writeln("I guess it does rule") ;
Matches are case-sensitive: if the pattern is /Javascript
rules/
, the result is false
. To instruct the pattern-matching
functions to ignore case, follow the second forward slash of the regular
expression with the letter i
:
var re =/Javascript rules/i;
The i
option is a flag that modifies the pattern matching, forcing the
matching process to disregard case. The other flags are g
for a global match and m
to match over
many lines.
The global match instructs the pattern-matching process to find
all occurrences of a pattern, regardless of where the pattern is in the
line. Without the use of the global flag g
, only the first match would either be
replaced or returned. The multiline flag m
enables the use of line-specific characters,
such as ^
for the start of a line and $
for the end, to work across multiple
lines.
If youâre creating a RegExp
object instance, the flags are passed as a second parameter:
var searchPattern = new RegExp('s+', 'g');
In the following snippet of code, the RegExp
method exec
searches for a specific pattern, /JS*/
, across the entire string (g
), ignoring case (i
). A string with the matched pattern,
available in the result array at the 0 index, is printed to the web
page, as is the location where the next match will begin:
var re = new RegExp("JS*","ig"); var str = "cfdsJS *(&YJSjs 888JS"; var resultArray = re.exec(str); while (resultArray) { document.writeln(resultArray[0]); document.writeln(" next match starts at " + re.lastIndex + "<br />"); resultArray = re.exec(str); }
The pattern described in the regular expression is the letter
J
, followed by any number of S
âs.
Since the i
flag is used, case is
ignored, so the js
substring is
found. As the g
flag is given, the
RegExp lastIndex
property is set to
the location where the last pattern was found on each successive call,
so each call to exec
finds the next
pattern. In all, the four items found are printed, and when no others
are found, a null value is assigned to the array. Because the loop
condition is just the array variable, setting the array to null results
in the loop terminating. Running this code results in the following
output:
JS next match starts at 6 JS next match starts at 13 js next match starts at 15 JS next match starts at 21
The exec
method returns an
array, but the array entries are not all matches, as you might have
initially guessed, but rather are the current match and any
parenthesized substrings. If you use parentheses to match substrings
within the overall string, they are included in successive array entries
in the resultant array following the overall matched string, contained
in the 0 index for the array. If you altered the preceding code snippet
to appear as in Example 4-6, other array
entries would show the substring pattern matches.
Example 4-6. String and substring matching with RegExp
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>RegExp string matching</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ window.onload=function() { var re = /(ds)+(j+s)/ig; var str = "cfdsJS *(&dsjjjsYJSjs 888dsdsJS"; var resultArray = re.exec(str); while (resultArray) { document.writeln(resultArray[0]); document.writeln(" next match starts at " + re.lastIndex + "<br />"); for (var i = 1; i < resultArray.length; i++) { document.writeln("substring of " + resultArray[i] + "<br />"); } document.writeln("<br />"); resultArray = re.exec(str); } } //]]> </script> </head> <body> <p></p> </body> </html>
The result from this example is:
dsJS next match starts at 6 substring of ds substring of JS dsjjjs next match starts at 16 substring of ds substring of jjjs dsdsJS next match starts at 31 substring of ds substring of JS
These code samples demonstrated a couple of the special regular
expression characters. There are several regular expression characters,
one of which is the plus sign (+
) in Example 4-6. Typically, books
and articles throw all such characters into a table, and then provide a
couple of examples that use several together in a long and complicated
pattern, and thatâs the extent of the coverage. Because of this, many
people have a lot of trouble putting together regular expressions, and
as a consequence, their applications donât work as they originally
anticipated. I think regular expressions are important enough to at
least provide several examples, from simple to complex. If you have
worked with regular expressions before, you might want to skip this
sectionâunless you need the review.
Though you use RegExp
methods
in applications, youâll primarily use regular expressions and the
RegExp
object with the String
objectâs regex
methods: replace
,
match
, and search
.
The rest of the examples in this section demonstrate regular expressions
using these methods.
You use the backslash character (\
), usually called the escape
character, to escape whatever character follows it. In JavaScript
regular expressions, the use of an escape character results in two
behaviors. If the character is usually treated literally, such as the
letter s
, itâs treated as a special character
following the escape characterâin this case, a whitespace (space, tab,
form feed, or line feed). Conversely, when you use the backslash with a
special character, such as the plus sign earlier, the character that
follows the backslash is treated as a literal.
The JavaScript application in Example 4-7 searches a string for instances of a space thatâs followed by an asterisk, and replaces the combination with a dash. Normally, the asterisk is used to match zero or more of the preceding characters in a regular expression, but in this case, we want to treat it as a literal.
Example 4-7. Escape character in regular expressions
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>RegExp</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function matchString() { var regExp = /\s\*/g; var str = "This *is *a *test *string"; var resultString = str.replace(regExp,'-'); alert(resultString); } //]]> </script> </head> <body onload="matchString()"> <p>Some page content</p> </body> </html>
Applying the regular expression against the string results in the following line:
This-is-a-test-string
The regular expression pattern used in Example 4-7 is a very handy
expression to keep in mind. If you want to replace all occurrences of
spaces in a string with dashes, regardless of whatâs following the spaces,
use the pattern /\s+\g
in the
replace
method, passing in the hyphen as the replacement character.
Four of the regular expression characters are used to match
specific occurrences of characters: the asterisk (*
) matches
the character preceding it zero or more times, the plus sign (+
) matches the character preceding it one or
more times, the question mark (?
)
matches zero or one of the preceding characters, and the period
(.
) matches exactly one
character.
Two patterns of interest are the greedy match
(.*
) and the lazy star (.*?
). In the first, because a period can
represent any character, the asterisk matches until the last occurrence
of a pattern, rather than the first. If youâre looking for anything
within quotes, you might think of using /".*"/
. If you use regular expressions with a
string, such as:
test='"one" or this is also a "test"'
the match begins with the first double quote and continues until the last one, not the second one:
"one" or this is also a "test"
The lazy star forces the match to end on the second occurrence of the double quote, rather than the last occurrence:
"one"
Example 4-8 contains a more complex regular expression. The application looks for a match on a date in the form of month name followed by space, day of month, and then year. The date begins after a colon.
Example 4-8. Patterns of repeating characters
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Find Date</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function findDate() { var regExp = /:\D*\s\d+\s\d+/; var str = "This is a date: March 12 2009"; var resultString = str.match(regExp); alert("Date" + resultString); } //]]> </script> </head> <body onload="findDate()"> <p>Some page content</p> </body> </html>
Looking more closely at the regular expression, the first
character in the pattern is the colon, followed by the backslash with a
capital letter D
: \D
. This sequence is one way to look for any
nonnumeric character; the asterisk following it means that any number of
nonnumeric characters will match. The next part in the regular
expression is a whitespace character, \s
, followed by another new pattern, \d
. Unlike the earlier sequence, \D
, the lowercase letter means to match
numbers only. The plus sign following this sequence means match one or
more numbers. Another space follows \s
in the pattern and then another sequence of
numbers, \d+
.
When matched against the string using String
match
, the date preceded by the colon is
found, returned, and printed:
Date: March 12 2009
In the example, \D
matches any
nonnumeric character. Another way to create this particular match is to
use the square brackets with a number range, preceded by the caret character
(^
). If you want to match any character except for numbers, use
the following:
[^0-9]
The same holds true for \d
,
except now you want numbers, so leave off the caret:
[0-9]
If you wish to match on more than one character type, you can list each range of characters within the brackets. The following matches on any upper- or lowercase letters:
[A-Za-z]
Using this alternative set of patterns, you also could give the regular expression in Example 4-8 as follows:
var regExp = /:[^0-9]*\s[0-9]+\s[0-9]+/;
You can use the caret (^
) in
another pattern: you use it and the dollar sign ($
) to
capture specific patterns relative to the beginning and end of a line.
When you use a caret outside the brackets, you match any sequence
beginning a line; the dollar sign matches any sequence ending a line. In
the following code snippet, the match is not successful because the character that was searched
did not occur at the beginning of the line:
var regExp = /^The/i; var str = "This is the JavaScript example";
However, the following would be successful:
var regExp = /^The/i; var str = "The example";
If the multiline flag is given (m
), the caret matches on the first character after the line
break:
var regExp = /^The/im; var str = "This is\nthe end";
The same positional pattern matching holds true for the end-of-line character. The following doesnât match:
var regExp = /end$/; var str = "The end is near";
But this does:
var regExp = /end$/; var str = "The end";
If the multiline flag is used, it matches at the end of the string and just before the line break:
var regExp = /The$/im; var str = "This is really the\nend";
The use of parentheses is significant in regular expression pattern matching. Parentheses match and then remember the match. The remembered values are stored in the result array:
var rgExp = /(^\D*[0-9])/ var str = "This is fun 01 stuff"; var resultArray = str.match(rgExp); document.writeln(resultArray);
In this code snippet, the array prints out This is fun 0
twice, separated by a comma,
indicating two array entries. The first result is the match; the second,
the stored value from the parentheses. If, instead of surrounding the
entire pattern, you surround only a portion, such as /(^\D*)[0-9]/
, this results in:
This is fun 0,This is fun
Only the surrounded matched string is stored.
Parentheses can also help you to switch material around in a
string. RegExp
recognizes special
characters, labeled $1
, $2
, and so
on, up to $9
, that store substrings
discovered through the use of the capturing parentheses. Example 4-9 finds pairs of
strings separated by one or more dashes and switches the
order of the strings.
Example 4-9. Swapping strings using regular expressions
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>swap</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function swapWords() { var rgExp = /(\w*)-*(\w*)/ var str = "Java---Script"; var resultStrng = str.replace(rgExp,"$2-$1"); alert(resultStrng); } //]]> </script> </head> <body onload="swapWords()"> <p>Some page content</p> </body> </html>
Hereâs the result of that JavaScript:
Script-Java
Notice that the number of dashes is also stripped down to just one
dash. This example introduces another very popular pattern-matching
character sequence, \w
. This sequence matches any alphanumeric
character, including the underscore (underline). Itâs equivalent to
[A-Za-z0-9_]
. Its converse is
\W
, which is equivalent to any
nonalphanumeric character.
The last regular expression characters weâll examine in detail are
the vertical bar (|
) and the curly
braces. The vertical bar indicates optional matches. For instance, the
following matches to either the letter a
or the
letter b
:
a|b
You can use more than one character with vertical bars to provide more options:
a|b|c
The curly braces indicate repetition of the preceding character a
set number of times. The following searches for two s
characters together:
s{2}
Regular expressions are extremely useful when processing data from Ajax applications, and when validating form contents, as I will demonstrate in Chapter 8.
In JavaScript, you use the Date
object
to create instances of dates. Once you have a date object instance, you
can use several methods to access or modify the date (or components of the
date) such as the year, day, and month.
Creating a date without passing in any parameters produces a date based on the client machineâs date and time:
var dtNow = new Date();
Or, you can pass in optional parameters to the Date
constructor to create a specific date. One
option is to pass in the number of milliseconds since January 1, 1970 at
12:00:00:
var dtMilliseconds = new Date(5999000920);
The preceding code snippet results in the following date:
Wed, 11 Mar 1970 10:23:20 GMT
You can also use a string to create a date as long as you use the proper date format:
var newDate = new Date("March 12, 1980 12:20:25");
You can forgo the time in the string and just get a date with times set to zeros:
var newDate = new Date('March 12, 2008');
You can also pass in each value of the date as integers, in order of year, month (as 0 to 11), day, hour, minutes, seconds, and milliseconds:
var newDt = new Date(1977,11,23); var newDt = new Date(1977,11,24,19,30,30,30);
The Date
object instance methods
feature several get
and set
methods for retrieving or setting specific
components of the date. Each of the following gets specific values from
the date according to local times:
Here are the Coordinated Universal Time (UTC) equivalents:
getUTCFullYear
getUTCHours
getUTCMilliseconds
getUTCMinutes
getUTCMonth
getUTCSeconds
getUTCDay
getUTCDate
Most of the get
methods have
equivalent set
methods that set a
componentâs value within a Date
. An
example would be setYear
to set the
year, setSeconds
to set the seconds, or
setUTCMonth
to set a UTC month. The
only method that doesnât have an equivalent set
method is getDay
. Also, two methods are deprecated,
meaning they wonât be available in the future. These are getYear
and setYear
.
Another method, getTimezoneOffset
, returns the number of minutes (+ or â) of the offset of the local
computer from UTC. Because Iâm writing this in St. Louis, which is in
UTC-5, I would get a value of 300 when calling this method against a local
time date.
Six methods convert the date to a formatted string:
Also, three static methods are available directly on the Date
object. Date.now
returns the current date and time; Date.parse
returns the number of milliseconds
since January 1, 1970; and Date.UTC
returns the number of milliseconds given the longest form of the
constructor, described earlier:
var numMs = Date.UTC(1977,11,24,30,30,30);
Note
Date.now
is not standard.
Creating a date primitive without using the new
constructor also returns the current
time:
var rightNow = Date();
Example 4-10
demonstrates several of the Date
methods, including those that set date components, and methods to display
the derived date.
Example 4-10. Several string setting and formatting Date methods
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Date</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function testingDate() { // new date var dtNow = new Date(); // set day, month, year dtNow.setDate(18); dtNow.setMonth(10); dtNow.setYear(1954); dtNow.setHours(7); dtNow.setMinutes(2); // output formatted document.writeln(dtNow.toString() + "<br />"); document.writeln(dtNow.toLocaleString() + "<br />"); document.writeln(dtNow.toLocaleDateString() + "<br />"); document.writeln(dtNow.toLocaleTimeString() + "<br />"); document.writeln(dtNow.toGMTString() + "<br />"); document.writeln(dtNow.toUTCString()); } //]]> </script> </head> <body onload="testingDate()"> <p>Some page content</p> </body> </html>
The result of running Example 4-10 in Firefox 3.1 is:
Thu Nov 18 1954 07:02:19 GMT-0600 (CST) Thu Nov 18 07:02:19 1954 11/18/1954 07:02:19 Thu, 18 Nov 1954 13:02:19 GMT Thu, 18 Nov 1954 13:02:19 GMT
Given so many date options, it might be puzzling to figure out which specific locale to use in an application. Iâve found that a good rule of thumb is to reference everything in the web page readerâs local time if her actions are isolatedâsuch as when placing an order at an online store. However, if the personâs actions are in relation to the actions of others, especially within an international audience (such as a weblog for comments), I recommend setting times to UTC to maintain a consistent framework for all of your readers.
Arithmetic isnât math, at least in JavaScript, where the operators for
basic arithmetic described in Chapter 3
are not associated with the Math
object. The Math
object provides
mathematical properties and methods, such as LN10
, which is the logarithm of 10, and log(x)
, which returns the natural logarithm of
x
. It doesnât participate in simple
arithmetic, such as addition and subtraction.
Unlike the other JavaScript objects, all of the Math
objectâs properties and methods are static.
This means you donât create a new instance of Math
to get access to the functionality; you
access the methods and properties directly on the shared object
itself:
var newValue = Math.SQRT1;
Several constant properties are
associated with the Math
object,
including the familiar pi, as well as the square root of 2 and the
national logarithm of 10. This following is a list of all of these
properties:
Math in programming depends somewhat on the underlying architecture, and this includes how each browser that provides a JavaScript engine implements some of the math functions, as well as the operating system, machine, and so on. As such, the results of the trigonometric functions may vary somewhat, but hopefully not so much as to make the functions unusable within this context.
The Math
methods are relatively straightforward. Regardless of variable
type, all arguments passed to the Math
functions are converted to numbers first.
You donât have to do any conversion in your code.
The abs
function takes an
argument representing a numeric value and returns the absolute value of that number. If the
number is negative, the positive value is returned. The variable
pVal
is set to 3.4 in the following
code snippet:
var nVal = -3.45; var pVal = Math.abs(nVal);
Several trigonometric methods are also available:
sin
, cos
, tan
,
acos
, asin
,
atan
, and atan2
.
These provide, respectively, the sine, cosine, tangent, arc cosine, arc
sine, arc tangent, and computation of the angle between an
x-point and the origin. Each takes a specific type
of numeric argument and returns a result that is meaningful to the
method:
The Math.ceil
method rounds a
number to the next highest whole number. The following two lines of
JavaScript set the variable pVal
to
4:
var nVal = 3.45; var pVal = Math.ceil(nVal);
The following lines of JavaScript set pVal
to â3:
var nVal = -3.45; var pVal = Math.ceil(nVal);
The Math.floor
method, on the other hand, rounds a number downâreturning the
next lowest whole number. The following JavaScript sets pVal
to 3:
var nVal = 3.45; var pVal = Math.floor(nVal);
The following lines of JavaScript sets pVal
to â4:
var nVal = -3.45; var pVal = Math.floor(nVal);
The Math.round
method rounds to the nearest integer; whether this is higher or
lower depends on the value. A value of 3.45 rounds to 3, whereas a value
of 3.85 rounds to 4. A midway number, such as 3.5, would round up to 4.
The result is the nearest integer regardless of whether the value is
negative or positive.
Math.exp(x)
calculates a number equivalent to e
, the base of natural logarithms, raised to
the value of the argument passed to the method:
var nVal = Math.exp(4) // equivalent to e4
Math.pow
raises any number to a given power:
var nVal = Math.pow(3,2) // 32 or 9
Math.min
and Math.max
compare two or more numbers and return the minimum or the
maximum:
var nVal = 1.45; var nVal2 = 4.5; var nVal3 = -3.33; var nResult = Math.min(nVal, nVal2, nVal3) // set to -3.33 var nResult2 = Math.max(nVal, nVal2, nVal3) // set to 4.5
The last method, Math.random
,
generates a number between 0 (inclusive) and 1 (exclusive):
var nValue = Math.random();
You can multiply this value by 10 or 100 (or by any value) to generate random numbers beyond a value of 1. Unfortunately, you canât set limits to generate a random number within a range of values. You can emulate this behavior, though, as Example 4-11 demonstrates.
Example 4-11. A random-number generator
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Random Quote</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function getQuote() { var quoteArray = new Array(5); quoteArray[0] = "Quote one"; quoteArray[1] = "Quote two"; quoteArray[2] = "Quote three"; quoteArray[3] = "Quote four"; quoteArray[4] = "Quote five"; iValue = Math.random(); // random number between 0 and 1 iValue *= 5; // multiply by 5 to move the decimal iValue = Math.floor(iValue); // round to nearest integer alert(quoteArray[iValue]); } //]]> </script> </head> <body onload="getQuote();"> <p>some content</p> </body> </html>
An array is created with five quotes. A function is called when
the page loads, which uses several Number
and Math
functions to generate an application
number (between 0 and 4 inclusive). The number is used to access an
array element, which is then output.
A JavaScript Array
is an object, just like String
or Math
. As such, you create it with a
constructor:
var newArray = new Array('one','two');
You also can create an array as a literal value, which doesnât
require the explicit use of the Array
object:
var newArray = ['one','two'];
Unlike String
and Number
, the JavaScript application immediately
converts the literal to an object of type Array
, assigning the result to the variable.
String
, Number
, and Boolean
literals are converted to objects only
when object methods are called, and then discard the object instances
immediately afterward.
Once the Array
instance is
created, you can access array elements by their index valueâthe number representing their location
in the array:
alert(newArray[0]);
Array indexes start at 0 and go up to the number of elements, minus 1. So, an array of five elements would have indexes from 0 to 4.
Arrays donât have to be one-dimensional. Itâs not uncommon to have an array in which each element has multiple dimensions, and the way to manage this in JavaScript is to create an array where each element is an array itself. In the following code snippet, an array of three-dimensional values is created:
var threedPoints = new Array(); threedPoints[0] = new Array(1.2,3.33,2.0); threedPoints[1] = new Array(5.3,5.5,5.5); threedPoints[2] = new Array(6.4,2.2,1.9);
If the inner array contains the x, y, and z coordinates in order, you can access the z coordinate of the third point with the following code:
var newZPoint = threedPoints[2][2]; // remember, arrays start with 0
To add array dimensions, continue creating arrays in elements:
threedPoints[2][2] = new Array(4.4,4.6,44) // and so on var newthreedZPoint = threedPoints[2][2][1];
You do not have to know the number of elements for an array ahead of time. As the examples demonstrate, you can create an array with a fixed number of elements in the array declaration, or just add elements as you go along. You can also set the size of an array by adding its nth or last element first:
var testArray = new Array(); testArray[99] = 'some value'; // testArray is now an array with 100 elements
To find the length of an array (the number of elements), use the
Array
property called length
:
alert(testArray.length); // outputs 100
If you access the length of a multiple-dimension array, youâll get the number of elements for only a particular dimension:
alert(threedPoints[2][2].length); // outputs 3 alert(threedPoints[2].length); // outputs 3 alert(threedPoints.length); // outputs 3
In addition to length
,
the Array
object also has a
few other properties of interest, and several methods. One such method is
splice
, which allows you to insert and/or remove elements from an arrayâa
rather handy method to have. In the following code snippet, splice
adds two elements and removes two,
starting at index 2 (the third element):
var fruitArray = new Array('apple','peach','orange','lemon','lime','cherry'); var removed = fruitArray.splice(2,2,'melon','banana'); document.writeln(removed + "<br />"); document.writeln(fruitArray);
The preceding code generates the following two lines:
orange,lemon apple,peach,melon,banana,lime,cherry
The removed elements are returned as an array from the splice
method call.
The slice
method slices an array
and returns the result:
var newFruit = fruitArray.slice(2,4); // returns an array of 3 elements: melon, banana, and lime
The concat
method
concatenates one array onto the end of the other, returning an array
with entries of apple, peach, melon, banana, lime, cherry, orange, and
lemon:
var newFruit = fruitArray.concat(removed);
Neither concat
nor slice
alters the original array. Instead, they
return a new array containing the results of the operation.
In the examples, Iâve been printing out the arrays directly. The
JavaScript engine converts the arrays to a string, using a default
separator of a comma (,
) between array
elements. If you want to designate a different separator, use the join
method to generate a string, passing in
what you want used as the separator, such as a space:
var strng = fruitArray.join(" ")
You can also reverse the order of the elements in an array using the
reverse
method:
fruitArray.reverse();
In many cases, the exact order of the elements in an array is unimportant. Sometimes, though, you want to have the order preserved, such as when the array serves as a queue. Several methods are useful for maintaining arrays as queues or lists, which weâll look at next.
You can use arrays to track a queue of items, where each is added
FIFO (first-in, first-out). Four handy Array
methods can maintain queues, lists, and
the like: push
, pop
, shift
,
and unshift
.
The push
method adds elements to the end of an array, whereas the
unshift
method adds elements to the
beginning of the array. Both return the new length of the array.
The pop
method removes the last
element of the array, and the shift
method removes the first element. Both return the element retrieved from
the array.
All four methods modify the arrayâeither adding or removing elements permanently from the array. Example 4-12 demonstrates how you can maintain a FIFO queue in JavaScript.
Example 4-12. FIFO queue using Array methods
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>FIFO</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> //<![CDATA[ function pushPop() { // create FIFO queue and add items using push var fifoArray = new Array(); fifoArray.push("Apple"); fifoArray.push("Banana"); var ln = fifoArray.push("Cherry"); // print out length and array document.writeln("length is " + ln + " and array is " + fifoArray + "<br />"); // use shift to shift the items off the array for (var i = 0; i < ln; i++) { document.writeln(fifoArray.shift() + "<br />"); } // print out length document.writeln("length now is " + fifoArray.length + "<br /><br />"); // now, same with unshift var fifoNewArray = new Array(); fifoNewArray.unshift("Learning"); fifoNewArray.unshift("Java"); ln = fifoNewArray.unshift("Script"); document.writeln("length is " + ln + " and array is " + fifoNewArray + "<br />"); // unshift for (var i = 0; i < ln; i++) { document.writeln(fifoNewArray.pop() + "<br />"); } document.writeln("new length is " + fifoNewArray.length ); } //]]> </script> </head> <body onload="pushPop();"> </body> </html>
The first thing to notice in this example is that Iâve paired
shift
and push
, and unshift
and
pop
. The reason for this is the order
in which these methods work. The push
method adds an element to the end of an array, and as each new element
is added, it pushes the first elements to the front of the array. The
pop
method removes the items from the
end of the array first, creating a LIFO list (last-in, first-out)âa
perfectly legitimate queue, but
not what weâre after with the program. We want the first element added
to be the first element retrieved. The shift
method removes elements from the top of
the array, which does suit our needs.
The same applies to unshift
and
pop
. The unshift
method adds items to the top of an
array, each new item pushing the older ones farther down the list, while
pop
removes them from the bottom of
the queue first. This again maintains the order of items, and this is
what weâre afterânot the order of the array elements themselves, but the
order in which theyâre added.
The result of running this JavaScript in our target browsers (all
except for current versions of Internet Explorer, which donât return a
length when using unshift
) is the
following:
length is 3 and array is Apple,Banana,Cherry Apple Banana Cherry length now is 0 length is 3 and array is Script,Java,Learning Learning Java Script new length is 0
Example 4-12 also
demonstrated how for
loops can
traverse an array. Rather than have to individually write out each
shift
or pop
method call, the application iterated
through the same call the same number of times as elements in the array.
This example is small, but you can imagine how much of a time-saver this
can be with a larger array.
Typically, when traversing an array with a for
loop, the variable thatâs adjusted with
each loop is incremented (or decremented when counting down) and is used
as an array index:
for (var i = 0; i < someArray.length; i++) { alert(someArray[i]); }
However, you do not have to use the index; itâs there if you need
it. And as implied, you count down with a for
loop as well as count up:
for (var i = someArray.length-1; i >= 0; i--) ...
As an alternative, you can use the for...in
loop to access each array
element:
var programLanguages = new Array ('C++','Pascal','FORTRAN','BASIC','C#','Java','Perl','JavaScript'); for (var itemIndex in programLanguages) { document.writeln(programLanguages[itemIndex] + "<br />"); }
Other methods are associated with the array that require the use of a callback function, which we will cover in Chapter 5.
Comma-separated strings are a common data format. How would you create an array of elements when given a comma-separated string? Write the code for the following string, and then access the third element:
"cats,dogs,birds,horses"
.The
\b
special character can define a word boundary, and\B
matches on a nonword boundary. Define a regular expression that will find all occurrences of the word fun in the following string and replace them with power:"The fun of functions is that they are functional."
Create code to get todayâs date, modify it by a week, and print out the new date.
Given a number of 34.44, write code that would round the number down. Do the same to round the number up.
Given a string such as the following, use pattern matching and replace all existing punctuation with commas, and then load it as an array and print out each value:
var str = "apple.orange-strawberry,lemon-.lime";
Use the
String.split
method, passing in a comma as the delimiter. Solution is:var animalString = "cats,dogs,birds,horses"; var animalArray = String.split(animalString,","); alert(animalArray[2]); // alert box displays birds
The solution is:
var funPattern = /\bfun\b/; var strToSearch = "The fun of functions is that they are functional"; var afterMatch = strToSearch.replace(funPattern,"power");
There is no
Date
function that manipulates weeks, but we know that a week is seven days at 24 hours a day, for a total of 168 hours. Use thegetHours
method to get the current dateâs hours, add 168 to it, reset the hours, and then print out the date:var dtNow = new Date(); var hours = dtNow.getHours(); hours+=168; dtNow.setHours(hours); document.writeln(dtNow.toString());
Math.floor
can round the number down, andMath.ceil
can round the number up. The solutions are:var baseNum = 34.44; var numFloor = Math.floor(baseNum); // returns 34 var numCeil = Math.ceil(baseNum); // returns 35
var strToAlter = "apple.orange-strawberry,lemon-.lime"; var puncPattern = /[\.|-]/g; var afterMatch = strToAlter.replace(puncPattern,","); var fruits = afterMatch.split(','); for (var i = 0; i < fruits.length; i++) document.writeln(fruits[i]);
Get Learning JavaScript, 2nd Edition 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.