JS Tip of the Day: Function Name Bindings

Function Name Bindings
Level: Intermediate

Named function expressions have an interesting behavior where they’ll create a variable binding of the function name with the function object local to the function body. This lets you easily refer to the function inside of the function if you’ve given it a name.

// listener that immediately removes itself after first call
document.addEventListener('click', function hookHang (event) {

    // hookHang = the current function
    document.removeEventListener('click', hookHang);

    console.log('My father hung me on a hook once.  ONCE.');
}); // ... or, alternatively, use the { once: true } option

Since this is local to the function, it does not create the variable in the parent scope.

let parentFunc = function localFunc () {
    console.log(typeof localFunc);
    console.log(typeof parentFunc);
/* logs

console.log(typeof localFunc); // undefined (only exists in function)
console.log(typeof parentFunc); // function

This is not a behavior you’ll see with function declarations. Though they are also named, they only create a variable binding for that name in the parent scope. You can see the difference if you overwrite the name of the declaration while attempting to access it inside the function.

let expr = function expr () {
    console.log(typeof expr);

let tempExpr = expr;
expr = undefined;
tempExpr(); // function (expressions work!)

function decl () {
    console.log(typeof decl);

let tempDecl = decl;
decl = undefined;
tempDecl(); // undefined (declarations don't)

You also get local name bindings for classes, though they work for both class expressions and class declarations.

class NamedClass {
    constructor () {
        console.log(typeof NamedClass);

let TempNamedClass = NamedClass;
NamedClass = undefined;
new TempNamedClass(); // function

More info:

More tips: JavaScript Tips of the Day