Skip to main content
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Mike Sprague
Ben Nadel at cf.Objective() 2017 (Washington, D.C.) with: Mike Sprague

Immediately Invoked Function Expressions (IIFE) Work In Lucee 5.3.2.77

By
Published in Comments (8)

Yesterday, at the end of day, I tweeted about something exciting that I had found in Lucee. It was the fact that the Immediately Invoked Function Expression construct - or IIFE (pronounced "iffy") - is supported in Lucee 5.3.2.77. More than anything, this is just a demonstration of how many things "just work" in the Lucee syntax, regardless of whether or not they are a good idea. The IIFE is a commonly-used pattern in the JavaScript world. But, if you are primarily a ColdFusion developer, this may not be a known pattern. As such, I wanted to showcase the feature support in Lucee.

An Immediately Invoked Function Expression (IIFE) is exactly what it sounds like: it is a function expression that is invoked as part of its own declaration. This is typically achieved by wrapping the function expression in a set of parenthesis and then invoking the expression as a Function:

( function expression )();

This invokes the function expression and returns the result of the function execution to the calling context.

In JavaScript, this is primarily done as a means to create a private scope that a set of revealed closures can act upon. To see this in action in Lucee CFML, we can create an IIFE that implements a simple counter:

<cfscript>
	
	// Our ID generator is created using an Immediately Invoked Function Expression, or
	// IIFE, which is simply a function that is executed as part of its definition. The
	// ID generator, in this case, then becomes the return value of the IIFE execution.
	nextID = (( numeric id = 0 ) => {

		// This inner function, that gets returned from the IIFE, closes-over the "id"
		// argument of the IIFE and can act upon it from the calling context even though
		// the rest of the world can't even see that it exists (this is just a closure).
		var incrementAndGet = () => {

			return( ++id );

		};

		return( incrementAndGet );

	})( 100 );

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

	echo( "ID: #nextID()# <br />" );
	echo( "ID: #nextID()# <br />" );
	echo( "ID: #nextID()# <br />" );

</cfscript>

As you can see here, we're defining a Function Expression that returns another Function, incrementAndGet(). We then immediately invoke that function expression and store the return value as our nextID variable. The IIFE, in this case, creates a private scope for the id value. The closure returned from the IIFE can then act upon this privately-scoped id value, even when passed out of scope (into the calling context).

Now, if we run this ColdFusion code, we get the following output:

ID: 101
ID: 102
ID: 103

As you can see, each call to the nextID() function - returned by the IIFE - incremented and returned the privately-scoped id value that is being "closed over" by the incrementAndGet() function.

Of course, you could achieve the same thing by simply defining an id variable and then directly calling ++id whenever you need the next ID in the series. I'm not trying to sell you on the idea of using an IIFE - I'm only demonstrating that it works in Lucee CFML.

Let's look at a slightly more robust example. In the following code, we're going to create an Immediately Invoked Function Expression (IIFE) that performs a depth-first traversal of the Element Nodes in an XML document. It will do this, in part, by exposing a small Iterator API:

<cfscript>

	// Create our XML document from the following HTML.
	doc = htmlParse("
		<html>
			<head>
				<title>Hello World</title>
			</head>
			<body>
				<h1>Hello World</h1>
				<p>Welcome to the <strong>fun zone</strong>!</p>
				<blockquote>The water is warm :D</blockquote>
			</body>
		</html>
	");

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

	// Create an iterator for our XML document using an IIFE - notice that the parsed
	// HTML document is provided as the ARGUMENT for our IIFE.
	iterator = (( required xml document ) => {

		// Since XPath performs a depth-first search of the document, the query for all
		// nodes will implicitly create an array over which we can easily walk.
		var nodes = document.search( ".//*" );
		var nodeCount = nodes.len();
		var nodeIndex = 0;

		// Return the API for our iterator.
		var api = {
			hasNext: () => {

				return( nodeIndex < nodeCount );

			},
			next: () => {

				if ( ! api.hasNext() ) {

					throw( type = "Iterator has run out of XML nodes to traverse!" );

				}

				return( nodes[ ++nodeIndex ] );

			}
		};

		return( api );

	})( doc );

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

	// Traverse the XML document and output the element names.
	while ( iterator.hasNext() ) {

		echo( "Element: " & iterator.next().xmlName & "<br />" );

	}

</cfscript>

In this case, we're providing the parsed HTML document as the argument to our IIFE. The IIFE then returns an Iterator API that will perform the depth-first traversal of the provided HTML document. In this case, the IIFE returns the hasNext() and next() methods, which "close over" the privately-scoped variables that store the location of the traversal within the context of XML document.

Now, if we run this ColdFusion code, we get the following output:

Element: html
Element: head
Element: title
Element: body
Element: h1
Element: p
Element: strong
Element: blockquote

As you can see, by using an IIFE, we are able to create small little chunks of cohesive functionality without having to dump too many variables into the share scope of the calling context.

I am loving the fact that Immediately Invoked Function Expressions (IIFE) are supported in Lucee. If nothing else, it's just a testament to how much the Lucee syntax "gets out of your way" and let's you get on with the business of solving problems. You may never need to use an IIFE in your Lucee CFML. But, it's nice to you know you can if you want to.

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

Reader Comments

10 Comments

Mind = Blown.

Very cool - I did not realize this was supported, thanks for sharing! Will definitely be keeping it in mind, to see if I can find a practical use case, or rather, just an excuse for using it.

449 Comments

Hi Ben. When you say IIFE, if, in the first example, there were no output commands, like:

echo( "ID: #nextID()# <br />" );

Would the:

nextID()

Function still execute?

Are you saying that these functions are self executing?
It seems like the last pair of parentheses, call the function immediately?
If so, this is kind of cool, although you could just call the function normally, but it creates a shortcut.

15,902 Comments

@Charles,

The "self-executing" part is the thing that produces the nextID() function, not the invocation of nextID() itself, if that makes sense. Basically, it's just this part:

(() => { ....... })();

Yeah, there are other ways to do this -- mostly, I was just excited that this actually worked from a syntax perspective.

449 Comments

OK. So:

nextID()

Returns the closure:

incrementAndGet()

And the following at the end:

( 100)

Seeds the method with the initial starting ID, which gets "remembered", when the closure is returned?

This is kind of clever, because the parent function makes everything inside privately scoped and only exposes the inner function to the outside world by returning it.

Like, in JavaScript:

(function(){
  var foo = 'Hello';
  var bar = 'World!'
  
  function baz(){
      return foo + ' ' + bar;
  }

  window.baz = baz; //Assign 'baz' to the global variable 'baz'...
})();

console.log(baz()); // public exposure
console.log(bar); // throws an exception: private variable

Your example is slightly different because it returns the inner function. But both provide a mechanism for exposing part of the content of the parent function!

15,902 Comments

@Charles,

Exactly, you are spot-on now! It's basically just like calling any other method that returns a function. If you "unwrap" the self-executing function, you are basically left with:

public any function createIdGenerator( numeric seedID = 0 ) {

	var id = seedID;
	
	var idGenerator = function() {
		return( ++id) );
	};

	return( idGenerator );

}

// Now, create a new ID generator.
nextID = createIdGenerator( 100 );

The only difference is that we are explicitly naming the intermediary function, createIdGenerator(), rather than just creating a headless function and invoking it immediately.

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