Regular Expressions—a Rite of Passage: From Theory to Practice
Tags: regex, dom, javascript
Published: 2023-02-05 00:34:39

![JavaScript in Plain English logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufpuszxu8iarolp0ytwo.png)
<h6>This article was first published on <a href="https://javascript.plainenglish.io">JavaScript in Plain English</a>.</h6>

<p><b>Part 2: Applying the theory to build a demo single-page app that validates zip codes.</b></p>

![Photo of woman's hands doing system design sketch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yc02qzncu9hrkeydpaek.jpg)
<h6><center>Photo by Kelly Sikkema on Unsplash</center></h6>

---

<h2>Table of Contents</h2>

---

#### _<a href="#welcome">WELCOME BACK!</a>_
#### <a href="#getStarted">Getting Started</a>
#### <a href="#build">Let's Build It!</a>
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#starterCode">Step 1. Unzip the Starter Code Archive</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#projectPieces">Step 2. Putting the Project Pieces Together</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#captureNodes">Step 3. Capture Necessary DOM Nodes</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#verifyNodes">Verify that Nodes Are Visible to the DOM</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#testRegExp">Step 4. Declare the Test String and Regular Expression</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#matches">Step 5. Use Regex to Return the Valid Zip Code Matches</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#helpers">Step 6. Creating the Helper Functions</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#createParagraphText">The createParagraphText() Helper Function</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#createParagraphs">The createParagraphs() Helper Function</a>_
##### &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_<a href="#appendParagraphs">The appendParagraphs() Helper Function</a>_
#### <a href="#next">What's Next?</a>

---

<a id="welcome"></a>
### _WELCOME BACK!_ 

For those of you who have read the first part in this tutorial series, thanks for hanging in through a theoretical article. It will pay off as we proceed from theory to practice.

In Part 2 we apply what we learned in Part 1, **_Regular Expressions&mdash;a Rite of Passage for Web Developers_**, which gave a quick introduction to some key concepts of regular expressions.

We will transform theory into practice by building a demo **Single Page Application (SPA)** for the web.

---

### Getting Started <a id="getStarted"></a>

For those who have not already seen what our SPA will look like, **Figure 1** below shows the landing page:


![Fig. 1 Application Landing Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgv6xhc152pukn67cdj9.png)
<h6><center>Fig. 1 Application Landing Page</center></h6>

---

The opening screen above presents the following components:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. The main heading, which states what the application does—namely,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matching valid zip codes.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Immediately below this, a callout box explains the aims of the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;application in more detail.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Next is a scrolling list of the multiline test string that will be passed to<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the regular expression shown below it.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Beneath this we have a **widget** that, on the left side, has a group of 2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vertically-stacked buttons. The top one, **Validate Zip Codes**, triggers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;an event that matches and extracts valid zip codes from the test<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string. When clicked, the window to its right is populated with valid zip<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;codes returned by the regular expression.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. The second button—**Reset**—resets the text box to its default state as<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;seen in **Figure 1**.

**_How are we going to do all of this?_** Let’s think about this for a second.

We provide some pre-fabricated test data to our application (though the principle would remain the same if a user were to upload a file with test data). In either case, the **regex engine** is presented with the test data and asked to return matches only for valid zip codes.

**This is more complicated than it sounds**. The regular expression specified to the regex engine must be able to do all of the following:

- Make certain that user input consists only of numbers and optionally a hyphen for +4 zip codes. (Obviously in the case of this demo application, there is no user input. But further development of this project could make the application fully interactive.)

- No alphabetical, punctuation, or other special symbols—save the hyphen needed in a +4 zip code—may be part of the returned match.

- Make certain that no other characters precede or follow either variety of zip codes (5-digit or +4).

- In every case, the zip code must start with a sequence of 5 digits.

- Optionally, the regex engine must be able to match a 5-character sequence followed by a hyphen and ending with a sequence of 4 numbers.

- Finally, no characters must occur after the last 4 digits.

All this seems a tall order. But as we saw in the previous tutorial, **regular expressions** are more than capable of fulfilling all these requirements.
 
**_The moment has finally arrived!_**

---

### Let’s Build It! <a id="build"></a>

After all this theory, let’s put it into practice and build this application.

To start, please download the [starter code](https://github.com/RHieger/regex-zip-code-tutorial/raw/starter-code/regex-starter-code.zip).

#### _Step 1. Unzip the Starter Code Archive_ <a id="starterCode"></a>

The archive is named **regex-starter-code.zip** You can rename it anything more to your liking, such as **regex-demo-web-app.zip**. Be sure to keep the **.zip** extension in the name as some zip archive programs might not recognize the file if the extension is missing.

For purposes of this tutorial, I use [Microsoft Visual Studio Code](https://code.visualstudio.com/), but you can also use your favorite text editor.

Once you have unzipped the renamed **regex-demo-web-app.zip** (or whatever name you choose), you will have a file structure similar to what is shown below in **Figure 2**.


![Fig. 2 Project File Structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zashaxzsg4a2y2idyyz.png)
<h6><center>Fig. 2 Project File Structure</center></h6>

---

#### _Step 2. Putting the Project Pieces Together_<a id="projectPieces"></a>

Our project is comprised of **HTML** content, **CSS** styling, and a single **JavaScript** file&mdash;**app.js**.

Though I have provided styling for you so that we can focus primarily on **JavaScript**, we will start at the bare-bones structure provided by the **index.html** file.

Let’s start by opening the application’s **index.html** file in your favorite<br>web browser. For purposes of this tutorial, I use **Google Chrome** for<br>its superb developer tools. **Figure 3** below shows our barebones<br>application framework.

![Fig 3. Bare Bones HTML](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18lnch1z38csdvejz4o2.png)
<h6><center>Fig. 3. Bare Bones HTML</center></h6>

---

**Figure 3** reveals the barebones structure of the document in which our application resides. Not all that comprehensible. Let’s fix that.

**Code Listing 1** below shows a fragment of our **index.html** file.

---

```html
<!-- INSERT link to zipcodes.css stylesheet. -->

<title>Regex Demo-Zip Code</title>

<!-- INSERT app.js JavaScript -->

</head>
```
<h6><center>Code Listing 1. index.html Showing Relevant &lt;head&gt; Content</center></h6>

---

We will replace the comment lines now with the code that will knit together the three components of our application.

As you know, in order for your browser to render the application landing page as we wish, we have to link our **cascading stylesheet** to the **HTML** file.

We also must link our **JavaScript** code to the HTML file. Follow these steps:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Open **index.html** if you have not already done so.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Search for the first comment in **Listing 1** above and replace it with the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;following code:
```
<link rel=“stylesheet” href=“./css/zipcodes.css”>
```
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Now we integrate the last component of our project. Search for the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;second comment in  **Code Listing 1** above and replace it with the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;following code:

```
<script src=“./js/app.js” defer></script>
```

The keyword **defer** in the `<script>` tag assures that the browser loads the DOM for the index.html document before script execution begins. This prevents JavaScript from throwing errors because a DOM object references a node that has not yet been defined.

Remember to save both these changes in your **index.html** file.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Refresh your browser.
 
Great! If all goes according to plan, your web page should appear exactly as in **Figure 1**.

However, if you click on either of the buttons, _absolutely nothing happens at this point._ Obviously, this is because we have yet to write any of the code that provides functionality to these buttons.

#### _Step 3. Capture Necessary DOM Nodes_<a id="captureNodes"></a>

Start by opening the **app.js** file included in the starter code archive.

At this point, the entire file consists of nothing more than comments. We start by capturing the necessary **DOM** nodes. We will use the **Document Object Model (DOM)** to pinpoint the parts of our screen that will need to change when the user interacts with our application.

_Which of the HTML elements need to be captured in DOM Objects?_ First, we can reason that because nothing happens when we click on either button in our application, we need to gain access to those nodes. Thus, we need 2 DOM objects to capture the **Validate Zip Codes** and **Reset** buttons.
Next we need two things to happen. We need the default message to the right of the buttons  that now reads **NO MATCH** to disappear and be replaced with a scrolling list of matches returned by the regex engine.

In order to do this, we need to be able to capture the default message so that it may be removed. We also need access to its parent element, which will contain the scrolling list once the default message is removed. Thus we need 2 DOM objects to capture these elements.

In total, we must declare 4 DOM objects to capture the nodes that reference the HTML elements to which we need access.

**Figure 4** below shows the relevant lines of HTML containing the elements we will capture in DOM objects:

---

![Fig. 4 Elements to Be Captured in the DOM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbg3g7kw9qgd5p456v72.png)
<h6><center>Fig. 4 Elements to Be Captured in the DOM</center></h6>

---

The critical pieces of markup in **Figure 4** are the buttons, the paragraph reading “no match,” and its parent element&mdash;the `<div>` with an **id** attribute of **“results.”**

Each element has an **id property** set on it so that it may be captured using the `document.getElementById()` method. There are other means that could be employed, such as the `querySelector()` and `querySelectorAll()` methods.

For this tutorial, I have chosen to use `getElementById()` for its directness and simplicity.

To create the necessary DOM objects, **search in your starter code** for the line  that reads `// TO BE DONE: Declare necessary DOM nodes` and replace it with the following 4 lines of code:

---

```javascript
const resultButton = document.getElementById(‘validate’);
const resetButton = document.getElementById(‘reset’);
const resultBox = document.getElementById(‘results’);
const placeHolder = document.getElementById(‘message’);
```
<h6><center>Code Listing 2: Code to Capture Required DOM Nodes</center></h6>

---

_Still_, nothing will happen if you refresh your browser and click on the **Validate Zip Codes** button. **We have not yet provided this functionality**. What we will do now is to test that the elements we captured are really captured, using the **Google Chrome Developer Tools**.

---

#### _Verify that the Nodes Are Visible to the DOM_<a id="verifyNodes"></a>

To do this, refresh your browser and open the **JavaScript Console** by pressing **Ctrl+Shift+J** for Windows/Linux/Unix and **Command+Option+J** for Mac. You should see something like **Figure 5** below:

---

![Fig. 5 Google Chrome Showing JavaScript Console on Right](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzt7scydmc5dsknxkdex.png)
<h6><center>Fig. 5 Google Chrome Showing JavaScript Console on Right</center></h6>

---

To verify our node objects, click an insertion point in the JavaScript Console and type the following commands followed by the **Enter/Return** key:

---

```
resultButton <Enter>
resetButton <Enter>
resultBox <Enter>
placeHolder <Enter>
```

---

Be sure to expand the output for **resultBox** by clicking on the right-pointing arrow next to the collapsed information.

You should see a result like that shown in **Figure 6** below:

---

![Fig. 6 Browser with JavaScript Console Confirming Access to the Desired Nodes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6h8uuj0x6n6n24hbdz9z.png)
<h6><center>Fig. 6 Browser with JavaScript Console Confirming Access to the Desired Nodes</center></h6>

---

As of now, we have our entry point into the application because we can access the portions of the page we need to manipulate. Next, we need to declare our test string and our regular expression.

---

### Step 4. Declare the Test String and Regular Expression<a id="testRegExp"></a>

We need to declare two **constants**&mdash;one that will store the **test string** we pass to our **regular expression** and one that stores the **regular expression object** to which the **test string** will be passed.

**Search in your starter code** for the line that reads `// TBD: Declare testString` and replace it with the following code:

---

```javascript
const testString =
`10003
asdf10003
10003asdf
jklm10003^$@%
10003-8924
one zero zero zero three
9101-94015
94015-9101
20012
08735
KbdsD$%^&*
sSd070031jkl;m
70122
\sKu2034
98108
75381
asdfjkl;
60661
!9004!@#$5^&*
97218
#,.$$&&%@
10022-3337
eNuhfF!.` ;
```
<h6><center>Code Listing 3. The Test String</center></h6>

---

**Search in your starter code** for the line that reads 

`// TO BE DONE: Declare regular expression.` 

and replace it with the following code:

---

```javascript
const regex = /^[0-9]{5}(-[0-9]{4})?$/gm;
```

---

The stage is set for our demo application. We have captured the **DOM nodes** that will be necessary to inject dynamic data to the page when the user clicks on the **Validate Zip Codes** button. We have also provided our **testString** constant and our **regex** constant.

Next, we have to move on to building the functionality that will provide the matches of valid zip codes that we want injected on our page.

---

### Step 5. Use Regex to Return the Valid Zip Code Matches<a id="matches"></a>

Before we actually add the necessary code to **app.js**, let’s take a step back to get a clear understanding of how the matching process will work.

We already have our regex object that was declared above using the object literal notation. This object exposes methods that perform different kinds of searches.

There are several methods exposed by the regex object. You can find them on the  Mozilla Developer Network regular expressions page ([_Using Regular Expressions in JavaScript"_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#using_regular_expressions_in_javascript)).

What will be relevant to us, however, is the `match()` method. The syntax for this method is:


---

```javascript
<string object>.match(<regular expression object>);
```

---

Our string object is the constant **testString**. The `match()` method, in turn, takes one argument, and that is the regular expression object.

The return value for `match()` is an array comprised of every match returned by the regular expression.

The return value **must be returned to something** in order for it to be accessible. In the syntax shown above, the object returned by the match() method is not addressable, though memory has been reserved for it.

Once the method is executed JavaScript will **garbage collect** the values stored therein as soon as it determines that they have not been used or are no longer in use. If you are interested in learning more about this,  you might want to consult this brief, but informative article on [garbage collection](https://javascript.info/garbage-collection) (_“Garbage Collection”_).
The actual syntax we will employ is as shown below:


---

```javascript
const myConstant = <string.object>
     .match(<regular expression object>);
```

---

**Search in your starter code** for the line that reads

`// TO BE DONE: Save regex match to matches variable.`

and replace it with:

---

```javascript
const match = testString.match(regex);
```

---

This one line of code accomplishes a lot. In one fell swoop, **testString** is passed to **regex** (our regular expression object), the pattern match is performed, valid zip codes are extracted, and the results are stored in an array with the identifier of **matches**. _Very powerful stuff._

---

Now let’s test this out by taking the steps that follow:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Refresh your browser. If you have not already opened the JavaScript<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console, do so now.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Click an insertion point in the JavaScript Console and type **matches**,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;then hit the **Enter/Return** Key. Once you expand the content<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returned in the console, your display should look like that shown in<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Figure 7** below:

---

![Fig. 7 Browser with JavaScript Console confirming valid zip code matches](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b5h83jb7e5pm6gygfknd.png)
<h6><center>Fig. 7 Browser with JavaScript Console confirming valid zip code matches</center></h6>

---

As **Figure 7** confirms there are 11 valid zip code matches returned by the **regular expression object**.

_Obviously, we cannot ask an end-user to enter the JavaScript Console to get the results of this validation process._ For this to be a truly dynamic application, we have to build some infrastructure preparatory to creating two **event listeners**&mdash;one that listens for a click on the **Validate Zip Codes** button, the other for a click on the **Reset** button.

### Step 6. Creating the Helper Functions<a id="helpers"></a>

_Of what is this infrastructure comprised?_ If we start with the most obvious assumption, we need something to happen when an end-user clicks either of the buttons.

Our application is **event-driven**. Thus we need to code two **event listeners** for the buttons. As we will see, these event listeners are powered by several **helper functions**.

Before we code the first helper, we need to declare an empty array, which its code will populate.


**Search in your starter code** for the line that reads

`// TO BE DONE: Declare empty array for text nodes.`

and replace it with:

---

```javascript
const paragraphText = [];
```

---

The above empty array will be populated by our first **helper function:**

---
<a id="createParagraphText"></a>
#### _The **createParagraphText()** Helper Function_

**Search in your starter code** for the line that reads

`// TO BE DONE: Code createParagraphText() helper function.`

and replace it with:

---

```javascript
const createParagraphText = () => {
  matches.forEach( match => {
    let matchNumber = matches.IndexOf(match) + 1;
    paragraphText.push(
      ` Match #${matchNumber}: ${match}`
    );
  };
};
```
<h6><center>Code Listing 4. The createParagraphText() Helper Function</center></h6>

---

_What is happening in this helper function?_ Let’s break it down line by line.

The code in `createParagraphText()` is comprised of a `forEach()` loop. `forEach()` is exposed by the **Array** object. In the code above, our array is the **matches** constant.

We call the `forEach()` method on **matches**. **match**, which is found in the **argument** portion of the method, is a reference to each element found in the **matches** array, over which it loops.

There is also an **anonymous callback function** as the second parameter, which extracts data from the `matches[]` array created by the `match()` method above. In the first line of the callback function, we declare the variable **matchNumber**, which stores the value of the **index + 1** within the `matches[]` array.

We call the `indexOf()` method on **match** to get the array index of **match** in each iteration of the loop. **1** is added to the index value because, as we know, arrays are **0-indexed**, and for humans, it makes more sense to refer to matches **1** through **11**, rather than **0** through **10**.

In the final line of our function, we populate the `paragraphText[]` array, using the `push()` method exposed by the Array object.

The data that we specify to be pushed to the array for each item makes use of both template literal notation and string interpolation to create an array element that looks like this:

---

```
Match #1: 10003
```

---

**You might be wondering why I didn’t create the full paragraph in one fell swoop.** Building the full paragraph comes as a result of our next helper function.

Before we build that, we need to declare another empty **array** to contain the completed paragraphs.

**Search in your starter code** for the line that reads

`// TO BE DONE: Declare paragraphs array to hold complete paragraphs.`

and replace it with:

---

```javascript
const paragraphs = [];
```

---

The `paragraphs[]` array will be populated by complete paragraphs with child text nodes extracted from the `paragraphText[]` array.

<a id="createParagraphs"><a/>
#### _The_ `createParagraphs()` _Helper Function_

**Search in your starter code** for the line that reads

`// TO BE DONE: Code createParagrahs() helper function.`

and replace it with:

---

```javascript
const createParagraphs = () => {
  paragraphText.forEach( text => {
    const paragraph = document.createElement(‘p’);
    paragraph.textContent = text;
    paragraphs.push(paragraph);
  };
};
```
<h6><center>Code Listing 5. the CreateParagraphs() Helper Function</center></h6>

---

_So what exactly is this code doing?_ The entire logic of the `createParagraphs()` function is found in a single call to the `forEach()` method.

The first line in the loop is:

```javascript
const paragraph = document.createElement(‘p’);
```

Let’s think about what’s happening here for a moment.

Each time through the loop, **JavaScript** finds a **text node** that is a member of the `paragraphText[]` array. This line of code declares a `<p>` element to which the **text node** will be appended as a **child**.

The next line in the loop is:

---

```javascript
paragraph.textContent = text;
```

---

This line appends the text node at the current index to the `<p>` element created in the previous line.

The final line of code in the loop is:

---

```javascript
paragraphs.push(paragraph);
```

---

This line of code pushes a complete paragraph to the `paragraphs[]` array. This sequence is repeated until the last element within the `paragraphText[]` array has been read into the loop.

An array of completed paragraphs now wait to be appended to the **resultBox** object. One final helper function will accomplish this task.

---

<a id="appendParagraphs"></a>
#### _The_ `appendParagraphs()` _Helper Function_

Let’s review **Figure 1** for a moment. The two buttons shown have to their right a box with a message that reads **NO MATCH**.

We want to swap the contents of this box now, removing the **NO MATCH** placeholder message with a scrolling window that will contain as its children all of the paragraphs in the `paragraphs[]` array.

**Search in your starter code** for the line that reads

`// TO BE DONE: Code createParagrahs() helper function.`

and replace it with:

---

```javascript
const appendParagraphs = (parent, children) => {
  children.forEach(  (child) => {
    parent.appendChild(child);
  });
};
```
<h6><center>Code Listing 6. The appendParagraphs() Helper Function</center></h6>

---

In only 5 lines of code, `appendParagraphs()` accomplishes quite a lot. The function takes two arguments, **parent** and **children**.

When calling this function, **parent** refers to **resultBox**, the node object that captures `<div id=“results”>` in our **index.html** file. **children** refers to the `paragraphs[]` array.

Our final helper function also uses the `forEach()` method. Here all elements of the `paragraphs[]` array are appended to the **resultBox** node, repeating this process until all 11 matches have been appended to **resultBox**.

---

> **IMPORTANT:** _If you try to log these nodes to the_  **JavaScript Console** _in your browser, you will receive an error message. This is because each of the_ **helper functions** _we have created up to this point is called by the_ **callback functions** _of the_ **event listeners** _we have yet to code._

---

We have now completed our infrastructure comprised of arrays and our 3 helper functions.

---

> **AN IMPORTANT ASIDE:** _You will note that in the_ `appendParagraphs()` _function, we have a fully abstracted function that is_ **de-coupled** _from the data sets in our application.<br><br>Though this could have been done for all the helper functions, in the interest of brevity, I have given this one example instead. This technique of_ **de-coupling** _functions from the data on which they operate makes the code more reusable and should be practice as a rule in public application releases._

---

### What’s Next?<a id="next"></a>

When you have completed all the steps above successfully, you can continue on with the third and concluding part of our tutorial&mdash;[**_Regular Expressions—a Rite of Passage: Completing the Application._**](url)

---

<h2><center>References</center></h2>

&ldquo;Regular Expressions - JavaScript: MDN, Using Regular Expressions in<br>&nbsp;&nbsp;&nbsp;&nbsp; in &nbsp;JavaScript&rdquo; _JavaScript | MDN_, Mozilla Developer Network,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#using_regular_expressions_in_javascript" target="_blank">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#using_regular_expressions_in_javascript</a>.

&ldquo;Garbage Collection.&rdquo; _The Modern JavaScript Tutorial,_ JavaScript.info,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;23 May 2022, <a href="https://javascript.info/garbage-collection" target="_blank">https://javascript.info/garbage-collection</a>.