Function expressions are functions
created where an expression is expected. You'll frequently encounter function
expressions as values assigned to a variable. Although a function declaration
always requires a name, you can use function expressions to create anonymous
functions by omitting the identifier and following the function
keyword with a
pair of parentheses containing optional parameters:
const myVariable = function() { };
You can then call those function expressions using the variable's identifier:
const myVariable = function() {
console.log( "This is my function." );
};
myVariable();
> "This is my function."
You can also use function expressions to create named functions using a syntax similar to function declarations:
const myVariable = function myFunction() {
console.log( "This is my function." );
};
myVariable();
> "This is my function."
However, unlike function declarations, a named function expression can be accessed by function name only within the function itself:
const myVariable = function myFunction() {
console.log( `I'm a ${ typeof myFunction }.`);
};
typeof myFunction;
> "undefined"
typeof myVariable;
> "function"
myVariable();
> "I'm a function."
Names associated with function expressions are primarily useful for debugging. A named function expression can also call itself recursively, though this isn't a very common use case in modern development:
const myVariable = function myFunction() {
console.log( "One second elapsed." );
setTimeout( myFunction, 1000 );
};
setTimeout( myVariable, 1000 );
> "One second elapsed."
> "One second elapsed."
> "One second elapsed."
…
Arrow function expressions
Arrow function expressions (often called "arrow functions" or, rarely, "lambda functions") were introduced in ES6 to provide a concise syntax for creating anonymous function expressions with some unique behaviors.
You can create an arrow function wherever an expression is expected, for
example, as a value assigned to a variable. In its most common form, an arrow
function is made up of a pair of matched parentheses containing zero or more
parameters, an arrow made up of a single equals sign and greater-than character
(=>
), and a pair of matched curly braces containing the function body:
const myFunction = () => {};
Under certain conditions, you can make the syntax even more compact. If you're only using one parameter, you can leave out the starting parentheses:
const myFunction = myParameter => {};
When you want the function body to return the value of a single expression,
neither enclosing the function body in curly braces nor
the return
keyword are required:
const myFunction = () => 2 + 2
myFunction()
> 4
Arrow functions are unique in that they don't have their own context for
arguments
or
this
values. Instead, they inherit both
values from the arrow function's
lexically enclosing environment, the nearest
enclosing function that does provide those contexts.
function myParentFunction() {
this.myProperty = true;
let myFunction = () => {
console.log( this );
}
myFunction();
};
let myInstance = new myParentFunction();
> Object { myProperty: true }
Call arrow functions
Arrow functions don't bind arguments in the same way as
other types of function.
An arguments
object in the body of an arrow function inherits its value from
that arrow function's closest
lexically enclosing environment:
function myFunction() {
let myArrowFunction = () => {
console.log( arguments[ 0 ] );
}
myArrowFunction( true );
};
myFunction( false );
> false
In this example, an outer function called with the argument false
calls an
inner arrow function with the argument true
. Because the arguments
object
inside the arrow function resolves to the binding in the outer function, the
inner function logs the outer function's false
.
If there's no arguments
object to inherit from the parent context, the arrow
function's arguments
object aren't defined, and trying to access it causes an
error:
let myArrowFunction = () => {
console.log(arguments);
};
myArrowFunction( true );
> Uncaught ReferenceError: arguments is not defined
Immediately Invoked Function Expressions (IIFE)
An Immediately Invoked Function Expression (IIFE), also sometimes called a "self-executing anonymous function," is a function expression that is called immediately when it's defined. An IIFE uses a function expression created by enclosing the function in a grouping operator. A second matched pair of parentheses then calls the function, either immediately following the function definition itself or immediately following the grouping operator. If you use a standard function, there's no practical difference between the two approaches:
(function() {
console.log( "IIFE.")
}
)();
> "IIFE."
(function() {
console.log( "IIFE.")
}
());
> "IIFE."
The first example calls the grouped function expression. The second example calls a function declaration inside the grouping operators, and the end result is then evaluated as a grouped expression. The result is the same in either case.
However, there is a difference when your IIFE is an arrow function. In this case, the parentheses used to call the function must be outside the grouping operators, because an arrow function on its own isn't an expression, but it must be created in a context where an expression is expected. Trying to call the arrow function from inside the scope of the grouping operators would mean calling an arrow function that hasn't yet been created in the context of an expression:
( () => {
console.log( "IIFE." );
}() );
> Uncaught SyntaxError: missing ) in parenthetical
Because the grouping operators expect an expression, the arrow function within them is defined, letting the parentheses that follow them call the grouped expression:
( () => {
console.log( "IIFE." );
} )();
> "IIFE."
Legacy applications, frequently used IIFEs to manage scope, specifically to avoid polluting the global scope with function-scoped variables and function declarations. Before the introduction of block scoping in ES6, it was common practice to wrap an entire script in an IIFE to prevent accidental pollution of the global scope.
Check your understanding
Can you call a named function expression by name outside the function?