Skip to main content
Ben Nadel at CFCamp 2023 (Freising, Germany) with: Luis Majano and Jürg Anderegg
Ben Nadel at CFCamp 2023 (Freising, Germany) with: Luis Majano ( @lmajano ) Jürg Anderegg

Using Labeled Loops In JavaScript

By on

Earlier this week, I looked at using labeled loops in ColdFusion. Labeled loops allow you to break and continue an outer loop from within the context of an inner loop by explicitly naming your loop statements. I had never used this functionality in ColdFusion before; and, it turns out, the same functionality is available in JavaScript. As such, I wanted to try it out in the browser as well.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

Modern ColdFusion looks more-or-less like modern JavaScript, especially when you take-out the type-checking (just another reason why ColdFusion is such an amazing language). In fact, I can pretty-much copy the "Fuzzy Matching" demo from my previous post and paste it in a JavaScript runtime with only slight modification.

In the following exploration, we're going to try and "fuzzy match" search text against a given target text. To do this, we're going to loop over the search text and - for each character in the search text - loop over the target text characters, trying to find a sequential match. This gives us the opportunity to explore a nested loop context.

ASIDE: This algorithm can be refactored to work without labeled loops, as Emre Yucel pointed out in my previous post. But, the point of this demo is to look at labeled loops. So, thank you for just going with the flow.

When a matching character is found within the inner loop, we will either continue or break out of the outer loop - using the outer loop label - based on the current condition:

<!doctype html>
<html lang="en">
<body>

	<h1>
		Using Labeled Loops In JavaScript
	</h1>

	<script type="text/javascript">

		// Fuzzy matches.
		console.log( isFuzzyMatch( "horse", "s" ) );
		console.log( isFuzzyMatch( "horse", "hs" ) );
		console.log( isFuzzyMatch( "horse", "horse" ) );

		// No matches.
		console.log( isFuzzyMatch( "horse", "horses" ) );
		console.log( isFuzzyMatch( "horse", "test" ) );
		console.log( isFuzzyMatch( "horse", "" ) );

		// --------------------------------------------------------------------------- //
		// --------------------------------------------------------------------------- //

		/**
		* I determine if the given target text is a fuzzy-match for the given search text.
		*/
		function isFuzzyMatch( targetValue, searchValue ) {

			var searchChars = [ ...searchValue ];
			var targetChars = [ ...targetValue ];
			var matchFound = false;
			var s, t;

			searchLoop:
			while ( s = searchChars.shift() ) {

				targetLoop:
				while ( t = targetChars.shift() ) {

					// We found a matching CHARACTER in the target string.
					if ( s == t ) {

						if ( ! searchChars.length ) {

							matchFound = true;
							// If we've run out of search-characters to consume, it means
							// that the entirety of the search keyword was located (in
							// parts) within the target text. In other words, we HAVE a
							// fuzzy-match. Yay! At this point, there is nothing left to
							// search and we can break out of BOTH the INNER and OUTER
							// loops.
							break searchLoop;

						}

						// If we have more search characters to consume, move onto the
						// NEXT ITERATION of the OUTER loop and the next search character.
						continue searchLoop;

					}

				}

				// If we've fully consumed the target characters, there's no sense in
				// continuing to consume the search characters - we will not find a match.
				break;

			}

			return( matchFound );

		}

	</script>

</body>
</html>

As you can see, each of the while-loops above is preceded by a label: statement. The outer loop is labeled as searchLoop:, which allows my inner loop to use break searchLoop and continue searchLoop statements. These will break out of or continue onto the next iteration of the outer loop, respectively.

FORMATTING NOTE: You can, technically, include the loop label on the same line as the loop itself. However, this should be avoided as it looks too much like Object-key assignment; and, is more likely to cause confusion.

Now, if we run this page in the browser we get the following console output:

true   // isFuzzyMatch( "horse", "s" )
true   // isFuzzyMatch( "horse", "hs" )
true   // isFuzzyMatch( "horse", "horse" )

false  // isFuzzyMatch( "horse", "horses" )
false  // isFuzzyMatch( "horse", "test" )
false  // isFuzzyMatch( "horse", "" )

As you can see, by using labeled loops, we were able to exert control flow on the outer loop from within the context of the inner loop. My demo uses while-loops but this also works for for-loops. In fact, you can even break out of a block - but that's just plain bananas!

Want to use code from this post? Check out the license.

Reader Comments

45 Comments

That's awesome news. I did a quick Google prior to posting and no docs from either Adobe nor Lucee came up. I've also heard Lucee present it, but not Adobe. Seems both of them need to beef up their docs!

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel