Javascript Interview Questions

JavaScript Interview Questions - Functions & Patterns

25 interview questions on higher-order functions, currying, function composition, IIFE, memoization, debouncing, throttling, and design patterns.

By TechCoder TeamLast updated: 2026-06-02
In a Nutshell

25 interview questions on higher-order functions, currying, function composition, IIFE, memoization, debouncing, throttling, and design patterns. This interview-focused guide covers essential javascript interview questions - functions & patterns concepts for technical interviews.

JavaScript Interview Questions – Functions & Patterns

Functions are first-class citizens in JavaScript. These 25 questions cover higher-order functions, currying, memoization, debouncing, throttling, IIFE, recursion, and common function design patterns.


1. What are higher-order functions?

A higher-order function takes a function as an argument or returns a function.

// Takes a function
[1, 2, 3].map(n => n * 2);
[1, 2, 3, 4].filter(n => n % 2 === 0);

// Returns a function
function multiplyBy(factor) {
    return number => number * factor;
}
const double = multiplyBy(2);

2. What is currying?

Transforms a function with multiple arguments into a sequence of unary functions.

// Normal: add(a, b, c)
// Curried: add(a)(b)(c)

const add = a => b => c => a + b + c;
console.log(add(1)(2)(3)); // 6

[!TIP] Currying is used extensively in functional programming and libraries like Redux middleware, Ramda, and Lodash/fp.

3. What is memoization?

Caches function results based on arguments to avoid redundant computations.

function memoize(fn) {
    const cache = new Map();
    return (...args) => {
        const key = JSON.stringify(args);
        if (!cache.has(key)) cache.set(key, fn(...args));
        return cache.get(key);
    };
}

const fib = memoize(n => n <= 1 ? n : fib(n - 1) + fib(n - 2));

4. What is debouncing?

Ensures a function is only called after a specified delay since the last invocation. Used for search inputs, window resize handlers.

function debounce(fn, delay = 300) {
    let timer;
    return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
    };
}

[!IMPORTANT] Debounce: Wait until user stops. Throttle: Execute at most once per interval. Use debounce for search, throttle for scroll.

5. What is throttling?

Ensures a function is called at most once in a specified time period.

function throttle(fn, limit = 200) {
    let inThrottle = false;
    return (...args) => {
        if (!inThrottle) {
            fn.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

6. What is an IIFE?

An Immediately Invoked Function Expression runs as soon as it's defined. Creates a private scope.

// Classic IIFE
(function() {
    const privateVar = "I'm private";
})();

// Module pattern with IIFE
const counter = (() => {
    let count = 0;
    return { increment: () => ++count, decrement: () => --count };
})();

7. What is function composition?

Combines functions where the output of one becomes the input of the next (right-to-left).

const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);

const addOne = x => x + 1;
const double = x => x * 2;
const transform = compose(double, addOne); // double(addOne(x))
console.log(transform(3)); // 8

8. What is the difference between call, apply, and bind?

  • call(thisArg, arg1, arg2) — invokes immediately with individual args
  • apply(thisArg, [args]) — invokes immediately with array arg
  • bind(thisArg, arg1, ...) — returns a new bound function (delayed execution)
function greet(g, p) { return `${g}, ${this.name}${p}`; }
const user = { name: "Alice" };
greet.call(user, "Hello", "!");     // "Hello, Alice!"
greet.apply(user, ["Hi", "?"]);     // "Hi, Alice?"
const bound = greet.bind(user, "Hey");
bound("!!");                         // "Hey, Alice!!"

9. What is the difference between Function Declaration and Function Expression?

  • Declaration: function foo() {} — hoisted, can be called before definition
  • Expression: const foo = function() {} — not hoisted, TDZ with let/const

10. What is recursion?

A function that calls itself. Requires a base case to terminate.

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

11. What is a pure function?

A function that (1) always returns the same output for the same input and (2) has no side effects (no modifying external state, no I/O).

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

// Impure
let total = 0;
const addToTotal = (n) => { total += n; return total; };

12. What are side effects?

Operations that modify state outside the function scope: DOM manipulation, API calls, console.log, modifying global variables, writing to files, mutating arguments.

13. What is a callback function?

A function passed as an argument to another function, invoked later (synchronously or asynchronously).

// Synchronous callback
[1, 2, 3].forEach(x => console.log(x));

// Asynchronous callback
setTimeout(() => console.log("Done"), 1000);

14. What is "callback hell" and how to avoid it?

Deeply nested callbacks that create hard-to-read pyramid code. Solutions: Promises (.then() chaining), async/await.

15. What is a generator function?

A function (function*) that can pause execution and resume later using yield.

function* idGen() {
    let id = 1;
    while (true) yield id++;
}

16. What is a factory function?

A function that returns a new object without using new.

function createUser(name, email) {
    return {
        name, email,
        greet() { return `Hi, I'm ${this.name}`; }
    };
}

[!TIP] Factory functions are an alternative to classes — they don't have this binding issues and work well with closures for private data.

17. What is the constructor pattern?

Uses new with a function to create objects. Sets up prototype chain automatically.

function Person(name) {
    this.name = name;
}
Person.prototype.greet = function() { return `Hi, ${this.name}`; };
const alice = new Person("Alice");

18. What is the module pattern?

Uses closures to create private variables and expose a public API.

const Database = (() => {
    const data = [];
    return {
        add(item) { data.push(item); },
        getAll() { return [...data]; }
    };
})();

19. What is the revealing module pattern?

A variation of the module pattern that defines all functions privately and exposes only selected ones.

20. What is the singleton pattern?

Ensures a class has only one instance and provides a global access point.

const Singleton = (() => {
    let instance;
    function create() { return { data: [] }; }
    return { getInstance: () => instance ||= create() };
})();

21. What is the observer (pub/sub) pattern?

Objects (observers) subscribe to events from another object (subject). When state changes, all observers are notified.

class EventEmitter {
    constructor() { this.events = {}; }
    on(event, fn) { (this.events[event] ||= []).push(fn); }
    emit(event, data) { this.events[event]?.forEach(fn => fn(data)); }
}

22. What are arrow function limitations?

  • No own this (lexical only)
  • No arguments object
  • Cannot be constructors
  • No prototype property
  • Cannot be generators
  • Cannot use yield (unless inside a generator)

23. What is the difference between parameters and arguments?

  • Parameters: Variables listed in function definition
  • Arguments: Actual values passed when calling the function

24. What is a method?

A function that is a property of an object.

const obj = {
    greet() { return "Hello"; } // Method
};

25. What is eval() and why is it dangerous?

Executes a string as JavaScript code. Security risk (code injection), prevents engine optimizations, and has performance issues.

[!CAUTION] Never use eval() in production. It's one of the most dangerous functions in JavaScript. Use JSON.parse() for data, not eval().