Skip to content
FLAVIO COPES
flaviocopes.com

JavaScript Immediately-invoked Function Expressions (IIFE)

By

Learn what a JavaScript Immediately-invoked Function Expression is, why the wrapping parentheses matter, how it creates scope, and when it is still useful.

~~~

An Immediately-invoked Function Expression, or IIFE, is a function expression that runs as soon as it is created.

Here’s the classic syntax:

(function() {
  console.log('Running now')
})()

The first parentheses turn the function into an expression. The final () call it immediately.

See the MDN function expression reference for the specification links and more examples.

Why use an IIFE?

Before JavaScript modules and block-scoped declarations, IIFEs were commonly used to keep variables out of the surrounding scope:

(function() {
  var message = 'Hello'
  console.log(message)
})()

typeof message //'undefined'

An IIFE can also calculate a value immediately:

const total = (function() {
  const price = 20
  const quantity = 3
  return price * quantity
})()

total //60

You can pass values as arguments:

(function(name) {
  console.log(`Hello, ${name}`)
})('Flavio')

Arrow function IIFEs

Arrow functions work too:

(() => {
  console.log('Running now')
})()

An async IIFE lets a classic script use await inside a local async function:

;(async () => {
  const response = await fetch('/data.json')
  const data = await response.json()
  console.log(data)
})()

JavaScript modules support top-level await in environments that implement it, so this pattern is often unnecessary in modules.

Named IIFEs

A regular function expression can have a name:

(function initialize() {
  console.log('Ready')
})()

The name is only available inside the function. It does not leak into the surrounding scope.

A name can make stack traces easier to understand.

The leading semicolon

You might see an IIFE start with a semicolon:

;(function() {
  console.log('Safe after previous code')
})()

This protects the expression when the previous statement has no semicolon and could be parsed as part of the IIFE call.

Modern bundlers normally handle statement boundaries, but the leading semicolon is still useful in standalone code that may follow unknown JavaScript.

Do you still need IIFEs?

Modules have their own top-level scope. Blocks with let and const also isolate local declarations:

{
  const message = 'Hello'
  console.log(message)
}

Use those simpler features when they solve the problem.

IIFEs remain useful when you need an expression that performs several steps immediately, or when you are working in a classic script without module scope.

~~~

Related posts about js: