Anonymous Function

An anonymous function is a function without a name. These functions are often used as arguments to other functions, assigned to variables, or used in situations where a function is needed only once.

Basic Anonymous Functions

javascript
// Regular function (named)
function greet() {
  console.log('Hello!');
}

// Anonymous function assigned to variable
const greet = function() {
  console.log('Hello!');
};

// Anonymous arrow function
const greet = () => {
  console.log('Hello!');
};

Common Use Cases

As Callback Functions

javascript
// setTimeout
setTimeout(function() {
  console.log('Delayed message');
}, 1000);

// Event listener
button.addEventListener('click', function() {
  console.log('Clicked!');
});

// Array methods
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map(function(n) {
  return n * 2;
});

const evens = numbers.filter(function(n) {
  return n % 2 === 0;
});

Immediately Invoked Function Expression (IIFE)

javascript
// IIFE - runs immediately
(function() {
  console.log('I run immediately!');
})();

// With parameters
(function(name) {
  console.log('Hello, ' + name);
})('World');

// Return value
const result = (function() {
  return 42;
})();

As Method Values

javascript
const obj = {
  // Anonymous function as method
  greet: function() {
    console.log('Hello!');
  },

  // Arrow function
  farewell: () => {
    console.log('Goodbye!');
  }
};

Anonymous vs Arrow Functions

Traditional Anonymous Function

javascript
const traditional = function(x, y) {
  return x + y;
};

// 'this' binding
const obj = {
  value: 42,
  getValue: function() {
    return this.value; // 'this' refers to obj
  }
};

Arrow Function

javascript
const arrow = (x, y) => x + y;

// 'this' is lexical
const obj = {
  value: 42,
  getValue: () => {
    return this.value; // 'this' is NOT obj!
  }
};

Arrow Function Syntax Variations

javascript
// No parameters
const greet = () => console.log('Hello');

// One parameter (parentheses optional)
const double = n => n * 2;
const double = (n) => n * 2;

// Multiple parameters
const add = (a, b) => a + b;

// Implicit return (one expression)
const square = n => n * n;

// Explicit return (block body)
const square = n => {
  return n * n;
};

// Return object literal (must wrap in parentheses)
const makePerson = (name, age) => ({ name, age });

// Multiline without return
const greet = name => {
  const message = `Hello, ${name}!`;
  console.log(message);
};

Advanced Patterns

Higher-Order Functions

javascript
// Return anonymous function
function multiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = multiplier(2);
const triple = multiplier(3);

console.log(double(5));  // 10
console.log(triple(5));  // 15

Closures

javascript
function counter() {
  let count = 0;

  return function() {
    return ++count;
  };
}

const increment = counter();
console.log(increment()); // 1
console.log(increment()); // 2
console.log(increment()); // 3

Function Composition

javascript
const compose = (...fns) => x =>
  fns.reduceRight((acc, fn) => fn(acc), x);

const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x * x;

const composed = compose(square, double, addOne);
console.log(composed(3)); // ((3 + 1) * 2)^2 = 64

React Examples

Event Handlers

jsx
function Button() {
  return (
    <button onClick={() => console.log('Clicked')}>
      Click me
    </button>
  );
}

// With parameters
function List({ items, onDelete }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>
          {item.name}
          <button onClick={() => onDelete(item.id)}>
            Delete
          </button>
        </li>
      ))}
    </ul>
  );
}

useEffect

jsx
function Component() {
  useEffect(() => {
    console.log('Component mounted');

    return () => {
      console.log('Component unmounted');
    };
  }, []);
}

Custom Hooks

jsx
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

Pros and Cons

Advantages

  • Concise syntax (especially arrow functions)
  • Good for one-time use functions
  • Useful in functional programming
  • Great for callbacks and closures
  • Prevent global namespace pollution (with IIFE)

Disadvantages

  • Harder to debug (no function name in stack traces)
  • Cannot be reused easily
  • Arrow functions don't have their own this
  • Cannot be used as constructors
  • Can reduce code readability if overused

When to Use Named vs Anonymous

Use Named Functions When:

javascript
// Reusable functionality
function validateEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

// Recursive functions
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

// Better stack traces
function handleComplexOperation() {
  // Complex logic
}

Use Anonymous Functions When:

javascript
// One-time callbacks
setTimeout(() => console.log('Done'), 1000);

// Array transformations
const doubled = numbers.map(n => n * 2);

// Inline event handlers
button.addEventListener('click', () => {
  console.log('Clicked once');
}, { once: true });

Common Patterns

Currying

javascript
const curry = fn => {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    }
    return (...nextArgs) => curried(...args, ...nextArgs);
  };
};

const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);

console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6

Memoization

javascript
const memoize = fn => {
  const cache = {};
  return (...args) => {
    const key = JSON.stringify(args);
    if (key in cache) {
      return cache[key];
    }
    const result = fn(...args);
    cache[key] = result;
    return result;
  };
};

const fibonacci = memoize(n => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

Best Practices

  • Use arrow functions for simple callbacks
  • Use named functions for complex logic or reusable code
  • Be mindful of this binding with arrow functions
  • Use descriptive variable names when assigning anonymous functions
  • Consider readability when choosing between named and anonymous
  • Use IIFE to avoid polluting global scope
  • Prefer arrow functions in modern JavaScript (ES6+)

TypeScript

typescript
// Type annotations
const add: (a: number, b: number) => number = (a, b) => a + b;

// Generic anonymous function
const identity = <T>(value: T): T => value;

// Function type
type Handler = (event: Event) => void;

const handleClick: Handler = (event) => {
  console.log('Clicked', event);
};

Learn More