JavaScript Frontend Interview Quick Guide (20 Minutes)

This guide covers key JavaScript concepts often asked in frontend interviews. Given the short timeframe (around 20 minutes for these topics), focus on understanding the core idea and being able to explain it clearly with a simple example.

1. Modern JavaScript (ES6+) Features

ES6 (ECMAScript 2015) and later versions introduced significant syntax improvements and features to make JavaScript more powerful, readable, and efficient.

Key Features:

let and const

Block-scoped variable declarations (see Scope/Hoisting section for details).

Arrow Functions

Concise syntax for functions. Lexically binds this.

// Traditional function
function add(a, b) {
  return a + b;
}

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

// With body
const multiply = (a, b) => {
  const result = a * b;
  return result;
};

Template Literals

String interpolation using backticks (\`) and ${expression}. Allows multi-line strings easily.

const name = 'John';
const age = 30;

// Old way
const message = 'Hello, my name is ' + name + ' and I am ' + age + ' years old.';

// Template literals
const message = `Hello, my name is ${name} and I am ${age} years old.`;

// Multi-line
const html = `
  <div>
    <h1>Hello ${name}</h1>
    <p>Age: ${age}</p>
  </div>
`;

Destructuring Assignment

Unpack values from arrays or properties from objects into distinct variables.

// Object destructuring
const user = { name: 'Alice', age: 25, city: 'NYC' };
const { name, age } = user;
console.log(name, age); // Alice 25

// Array destructuring
const colors = ['red', 'green', 'blue'];
const [first, second] = colors;
console.log(first, second); // red green

// With default values
const { country = 'USA' } = user;
console.log(country); // USA

// Nested destructuring
const person = {
  name: 'Bob',
  address: {
    city: 'Boston',
    zip: '02101'
  }
};
const { address: { city } } = person;
console.log(city); // Boston

Spread (...) / Rest (...) Operators

Spread: Expands iterables into individual elements.

Rest: Collects multiple function arguments into a single array parameter.

// Spread operator
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }

// Rest parameter
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

// Rest in destructuring
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest);  // [2, 3, 4, 5]

Classes

Syntactic sugar over JavaScript's prototype-based inheritance.

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  greet() {
    console.log(`Hello, I'm ${this.name}`);
  }
  
  static species() {
    return 'Homo sapiens';
  }
}

class Employee extends Person {
  constructor(name, age, jobTitle) {
    super(name, age);
    this.jobTitle = jobTitle;
  }
  
  work() {
    console.log(`${this.name} is working as ${this.jobTitle}`);
  }
}

const emp = new Employee('John', 30, 'Developer');
emp.greet(); // Hello, I'm John
emp.work();  // John is working as Developer

Modules (import/export)

Native way to organize code into reusable files/modules.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export default class Calculator {
  multiply(a, b) {
    return a * b;
  }
}

// app.js
import Calculator, { add, subtract } from './math.js';
console.log(add(5, 3));        // 8
console.log(subtract(5, 3));   // 2
const calc = new Calculator();
console.log(calc.multiply(5, 3)); // 15

Potential Interview Questions:

  • Can you explain the difference between var, let, and const?
  • What are the benefits of using arrow functions?
  • Show me an example of object or array destructuring.
  • What's the difference between the Spread and Rest operators?

Try ES6+ Features

Code Editor
Console Output
Click "Run" to execute your code...

2. JS Execution Context

The environment or "box" where JavaScript code is evaluated and executed. Every time code runs, it's within an execution context.

Key Points:

Types of Execution Context

  • Global Execution Context (GEC): Base context for code running in the global scope
  • Function Execution Context (FEC): Created whenever a function is invoked

Creation Phase

Memory is allocated. The engine sets up:

  • Variable Environment (hoists variable/function declarations)
  • Scope Chain
  • Determines the value of this

Execution Phase

Code is executed line by line. Values are assigned to variables.

Call Stack (Execution Stack)

Manages execution contexts. When a function is called, its FEC is pushed onto the stack. When it returns, it's popped off. The GEC is at the bottom.

// Example of Execution Context
var x = 10;

function outer() {
  var y = 20;
  
  function inner() {
    var z = 30;
    console.log(x + y + z); // 60
  }
  
  inner();
}

outer();

// Execution flow:
// 1. Global Execution Context created
//    - x = undefined (creation phase)
//    - outer function stored
// 2. Global Execution Phase
//    - x = 10
//    - outer() called
// 3. outer() Function Execution Context created
//    - y = undefined
//    - inner function stored
// 4. outer() Execution Phase
//    - y = 20
//    - inner() called
// 5. inner() Function Execution Context created
//    - z = undefined
// 6. inner() Execution Phase
//    - z = 30
//    - console.log executed
// 7. inner() context popped off
// 8. outer() context popped off
// 9. Back to Global context

Potential Interview Questions:

  • What is an execution context?
  • Explain the Call Stack and how it relates to function calls.
  • What happens during the creation phase of an execution context?

3. Event Loop in JS

JavaScript is single-threaded, but it handles asynchronous operations without blocking the main thread using the Event Loop mechanism.

Key Components:

  • Call Stack: Where synchronous code execution happens
  • Web APIs / C++ APIs: Handle asynchronous tasks (setTimeout, fetch, DOM events)
  • Callback Queue (Task Queue): Holds callbacks for async tasks that have completed
  • Microtask Queue: Holds Promise callbacks (.then, .catch, .finally) - higher priority
  • Event Loop: Continuously checks if Call Stack is empty, then processes microtasks, then tasks
// Event Loop Example
console.log('1: Start');

setTimeout(() => {
  console.log('2: Timeout');
}, 0);

Promise.resolve().then(() => {
  console.log('3: Promise');
});

console.log('4: End');

// Output:
// 1: Start
// 4: End
// 3: Promise (Microtask - higher priority)
// 2: Timeout (Callback Queue - lower priority)

// More complex example
console.log('A');

setTimeout(() => console.log('B'), 0);

Promise.resolve()
  .then(() => console.log('C'))
  .then(() => console.log('D'));

console.log('E');

// Output: A, E, C, D, B

How It Works:

1. Execute synchronous code (Call Stack)
2. When async operation completes:
   - Promise callbacks → Microtask Queue
   - Other callbacks → Callback Queue
3. When Call Stack is empty:
   - Process ALL microtasks
   - Then process ONE task from Callback Queue
   - Repeat

Potential Interview Questions:

  • How does JavaScript handle asynchronous operations if it's single-threaded?
  • Explain the roles of the Call Stack, Callback Queue, and Event Loop.
  • What's the difference between the Microtask Queue and the Callback Queue?

Try Event Loop Examples

Code Editor
Console Output
Click "Run" to execute your code...

4. Promises in JS

An object representing the eventual completion (or failure) of an asynchronous operation and its resulting value.

Promise States:

  • Pending: Initial state, neither fulfilled nor rejected
  • Fulfilled: Operation completed successfully (resolves with a value)
  • Rejected: Operation failed (rejects with an error/reason)
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
  const success = true;
  
  setTimeout(() => {
    if (success) {
      resolve('Operation successful!');
    } else {
      reject('Operation failed!');
    }
  }, 1000);
});

// Using a Promise
myPromise
  .then(result => {
    console.log(result); // Operation successful!
    return 'Next value';
  })
  .then(value => {
    console.log(value); // Next value
  })
  .catch(error => {
    console.error(error);
  })
  .finally(() => {
    console.log('Cleanup or final action');
  });

Promise Chaining

// Chaining promises
fetch('https://api.example.com/user/1')
  .then(response => response.json())
  .then(user => {
    console.log('User:', user);
    return fetch(`https://api.example.com/posts?userId=${user.id}`);
  })
  .then(response => response.json())
  .then(posts => {
    console.log('Posts:', posts);
  })
  .catch(error => {
    console.error('Error:', error);
  });

async/await

Syntactic sugar built on top of Promises, making async code look synchronous.

// Using async/await
async function fetchUserData() {
  try {
    const userResponse = await fetch('https://api.example.com/user/1');
    const user = await userResponse.json();
    console.log('User:', user);
    
    const postsResponse = await fetch(`https://api.example.com/posts?userId=${user.id}`);
    const posts = await postsResponse.json();
    console.log('Posts:', posts);
    
    return { user, posts };
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

// async functions always return a Promise
fetchUserData().then(data => console.log('Done:', data));

Promise Static Methods

// Promise.all - waits for all promises (fails if any fails)
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise(resolve => setTimeout(() => resolve('foo'), 100));

Promise.all([promise1, promise2, promise3])
  .then(values => console.log(values)); // [3, 42, 'foo']

// Promise.race - first to settle wins
Promise.race([
  new Promise(resolve => setTimeout(() => resolve('slow'), 500)),
  new Promise(resolve => setTimeout(() => resolve('fast'), 100))
]).then(value => console.log(value)); // 'fast'

// Promise.allSettled - waits for all, doesn't fail
Promise.allSettled([
  Promise.resolve('success'),
  Promise.reject('error')
]).then(results => console.log(results));
// [{ status: 'fulfilled', value: 'success' }, { status: 'rejected', reason: 'error' }]

Potential Interview Questions:

  • What problem do Promises solve? (Callback hell, better async management)
  • What are the different states of a Promise?
  • Explain how async/await works and how it relates to Promises.
  • What's the difference between Promise.all and Promise.race?

5. Single Threaded JS

JavaScript code execution runs on a single main thread. This means it can only perform one operation at a time in a specific order.

Key Concepts:

One Task at a Time

Instructions are executed sequentially. If a task takes a long time (e.g., complex calculation), it blocks subsequent code from running, potentially freezing the UI in browsers.

Concurrency Model

Asynchronous operations (I/O, timers) are handed off to the environment (Browser APIs, Node.js APIs) which operate potentially on different threads. When these tasks complete, their callbacks are queued for execution back on the main JS thread via the Event Loop.

// Blocking code (BAD)
console.log('Start');

// This blocks for 3 seconds!
const end = Date.now() + 3000;
while (Date.now() < end) {
  // Busy waiting - blocks the thread
}

console.log('End after 3 seconds');

// Non-blocking code (GOOD)
console.log('Start');

setTimeout(() => {
  console.log('This runs after 3 seconds');
}, 3000);

console.log('End immediately');
// The main thread is free to do other work!

Implications

  • Must write non-blocking code using async patterns
  • Long-running computations should be broken up or moved to Web Workers
  • I/O operations should always be asynchronous
  • UI responsiveness depends on keeping the main thread free

Potential Interview Questions:

  • What does it mean that JavaScript is single-threaded?
  • If JS is single-threaded, how can it perform tasks like fetching data without freezing?
  • What is 'blocking' in JavaScript?

6. IIFE (Immediately Invoked Function Expressions)

A JavaScript function that is defined and executed as soon as it's created.

Syntax:

// Method 1
(function() {
  // code here
})();

// Method 2
(function() {
  // code here
}());

// Arrow function IIFE
(() => {
  // code here
})();

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

Primary Use Cases:

1. Create Private Scope
// Without IIFE - global pollution
var count = 0;
function increment() {
  count++;
}
// count is accessible globally

// With IIFE - private scope
(function() {
  var count = 0;
  function increment() {
    count++;
    console.log(count);
  }
  increment(); // 1
  increment(); // 2
})();

// console.log(count); // ReferenceError: count is not defined
2. Module Pattern
const calculator = (function() {
  // Private variables
  let result = 0;
  
  // Private function
  function validate(num) {
    return typeof num === 'number';
  }
  
  // Public API
  return {
    add: function(num) {
      if (validate(num)) {
        result += num;
      }
      return this;
    },
    subtract: function(num) {
      if (validate(num)) {
        result -= num;
      }
      return this;
    },
    getResult: function() {
      return result;
    }
  };
})();

calculator.add(5).add(3).subtract(2);
console.log(calculator.getResult()); // 6
// console.log(calculator.result); // undefined (private!)
3. Avoid Variable Collisions
// Library A
(function() {
  var $ = 'Library A';
  console.log($);
})();

// Library B
(function() {
  var $ = 'Library B';
  console.log($);
})();

// No conflict!

Modern Relevance

Less common now due to ES6 Modules providing a standard, cleaner way to manage scope and dependencies. Still useful occasionally for specific scoping needs or in environments without module support.

Potential Interview Questions:

  • What is an IIFE and why would you use one?
  • Are IIFEs still necessary with ES6 modules?
  • How do IIFEs help with variable scope?

Try IIFE Examples

Code Editor
Console Output
Click "Run" to execute your code...

7. Scope and Hoisting

Scope

Determines the accessibility (visibility) of variables and functions at various parts of your code during runtime.

Types of Scope:

1. Global Scope

Variables declared outside any function or block. Accessible everywhere.

var globalVar = 'I am global';

function test() {
  console.log(globalVar); // Accessible
}

test();
console.log(globalVar); // Accessible
2. Function Scope

Variables declared inside a function. Accessible only within that function.

function myFunction() {
  var functionVar = 'I am function-scoped';
  console.log(functionVar); // Works
}

myFunction();
// console.log(functionVar); // ReferenceError
3. Block Scope

Variables declared inside a block ({ ... }) using let or const. var is NOT block-scoped.

if (true) {
  var varVariable = 'var is NOT block-scoped';
  let letVariable = 'let is block-scoped';
  const constVariable = 'const is block-scoped';
}

console.log(varVariable);    // Works
// console.log(letVariable);    // ReferenceError
// console.log(constVariable);  // ReferenceError

// Loop example
for (var i = 0; i < 3; i++) {
  // i is accessible outside
}
console.log(i); // 3

for (let j = 0; j < 3; j++) {
  // j is block-scoped
}
// console.log(j); // ReferenceError

Hoisting

JavaScript's default behavior of moving declarations (but not initializations) to the top of their containing scope before code execution.

var Hoisting

console.log(x); // undefined (not ReferenceError)
var x = 5;
console.log(x); // 5

// Behind the scenes:
// var x;           // Declaration hoisted
// console.log(x);  // undefined
// x = 5;           // Assignment stays
// console.log(x);  // 5

let and const - Temporal Dead Zone (TDZ)

// console.log(y); // ReferenceError
let y = 10;

// console.log(z); // ReferenceError
const z = 20;

// let and const are hoisted but not initialized
// Accessing before declaration = TDZ error

Function Hoisting

// Function Declaration - fully hoisted
sayHello(); // Works!
function sayHello() {
  console.log('Hello');
}

// Function Expression - only variable hoisted
// sayGoodbye(); // TypeError: sayGoodbye is not a function
var sayGoodbye = function() {
  console.log('Goodbye');
};
sayGoodbye(); // Works now

// Arrow Function - same as function expression
// greet(); // ReferenceError or TypeError
const greet = () => console.log('Hi');
greet(); // Works now

var vs let vs const Summary

Featurevarletconst
ScopeFunctionBlockBlock
HoistingYes (initialized with undefined)Yes (in TDZ)Yes (in TDZ)
ReassignableYesYesNo
Must InitializeNoNoYes

Potential Interview Questions:

  • Explain the difference between var, let, and const in terms of scope and hoisting.
  • What is hoisting in JavaScript?
  • What is the Temporal Dead Zone (TDZ)?
  • What's the difference in hoisting between function declarations and function expressions?

8. Callbacks in JS

A function that is passed as an argument to another function, with the intention of being executed ("called back") at a later time, often after an asynchronous operation has completed.

Basic Callback Example:

function greet(name, callback) {
  console.log('Hello, ' + name);
  callback();
}

function sayGoodbye() {
  console.log('Goodbye!');
}

greet('John', sayGoodbye);
// Output:
// Hello, John
// Goodbye!

Asynchronous Callbacks

// setTimeout
console.log('Start');

setTimeout(function() {
  console.log('This runs after 2 seconds');
}, 2000);

console.log('End');

// Output:
// Start
// End
// This runs after 2 seconds

// Event listeners
document.getElementById('button').addEventListener('click', function() {
  console.log('Button clicked!');
});

// Reading files (Node.js)
const fs = require('fs');
fs.readFile('file.txt', 'utf8', function(err, data) {
  if (err) {
    console.error('Error:', err);
    return;
  }
  console.log('File contents:', data);
});

Higher-Order Functions with Callbacks

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

// map
const doubled = numbers.map(function(num) {
  return num * 2;
});
console.log(doubled); // [2, 4, 6, 8, 10]

// filter
const evens = numbers.filter(function(num) {
  return num % 2 === 0;
});
console.log(evens); // [2, 4]

// forEach
numbers.forEach(function(num) {
  console.log(num);
});

// reduce
const sum = numbers.reduce(function(total, num) {
  return total + num;
}, 0);
console.log(sum); // 15

Callback Hell (Pyramid of Doom)

Deeply nested callbacks can become hard to read and maintain.

// BAD - Callback Hell
getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      getMoreData(c, function(d) {
        getMoreData(d, function(e) {
          console.log('Finally done!', e);
        });
      });
    });
  });
});

// BETTER - Using Promises
getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => getMoreData(d))
  .then(e => console.log('Finally done!', e))
  .catch(error => console.error(error));

// BEST - Using async/await
async function processData() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getMoreData(b);
    const d = await getMoreData(c);
    const e = await getMoreData(d);
    console.log('Finally done!', e);
  } catch (error) {
    console.error(error);
  }
}

Error-First Callback Pattern (Node.js)

function readFile(filename, callback) {
  // Simulated async operation
  setTimeout(() => {
    const error = null; // or new Error('File not found')
    const data = 'File contents';
    
    // First argument is always error
    callback(error, data);
  }, 1000);
}

readFile('example.txt', function(err, data) {
  if (err) {
    console.error('Error:', err);
    return;
  }
  console.log('Data:', data);
});

Potential Interview Questions:

  • What is a callback function?
  • Can you give an example of where callbacks are used?
  • What is 'callback hell' and how can it be avoided?
  • What is a higher-order function?

Try Callbacks

Code Editor
Console Output
Click "Run" to execute your code...

9. Navigator Object

The Navigator object contains information about the browser and the user's system. It's available as window.navigator or just navigator.

Common Properties and Methods:

// Browser information
console.log(navigator.userAgent);     // Browser user agent string
console.log(navigator.appName);       // Browser name
console.log(navigator.appVersion);    // Browser version
console.log(navigator.platform);      // Operating system platform

// Language
console.log(navigator.language);      // User's preferred language
console.log(navigator.languages);     // Array of preferred languages

// Online status
console.log(navigator.onLine);        // true if online, false if offline

// Cookies enabled
console.log(navigator.cookieEnabled); // true if cookies enabled

// Hardware
console.log(navigator.hardwareConcurrency); // Number of CPU cores

// Geolocation
navigator.geolocation.getCurrentPosition(
  position => {
    console.log('Latitude:', position.coords.latitude);
    console.log('Longitude:', position.coords.longitude);
  },
  error => {
    console.error('Error getting location:', error);
  }
);

// Clipboard API
navigator.clipboard.writeText('Hello, World!')
  .then(() => console.log('Text copied to clipboard'))
  .catch(err => console.error('Failed to copy:', err));

navigator.clipboard.readText()
  .then(text => console.log('Clipboard contents:', text))
  .catch(err => console.error('Failed to read:', err));

// Service Workers
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => console.log('Service Worker registered'))
    .catch(error => console.error('Registration failed:', error));
}

// Media Devices
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
  .then(stream => {
    // Use the stream (camera/microphone access)
  })
  .catch(error => console.error('Media access denied:', error));

// Battery Status
navigator.getBattery().then(battery => {
  console.log('Battery level:', battery.level * 100 + '%');
  console.log('Charging:', battery.charging);
});

Feature Detection

Use Navigator to detect browser capabilities before using features:

// Check if features are available
if ('geolocation' in navigator) {
  // Geolocation is available
}

if ('serviceWorker' in navigator) {
  // Service Workers are supported
}

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  // Camera/microphone access available
}

if (navigator.clipboard) {
  // Clipboard API is available
}

User Agent Detection (Use with Caution)

const ua = navigator.userAgent.toLowerCase();

if (ua.includes('chrome')) {
  console.log('Chrome browser');
} else if (ua.includes('firefox')) {
  console.log('Firefox browser');
} else if (ua.includes('safari')) {
  console.log('Safari browser');
}

// Better: Feature detection instead of browser detection
if (typeof window.IntersectionObserver !== 'undefined') {
  // Use IntersectionObserver
} else {
  // Fallback or polyfill
}

Potential Interview Questions:

  • What is the Navigator object used for?
  • How would you detect if a user is online or offline?
  • Why is feature detection better than browser detection?
  • How can you access the user's geolocation?

Quick Reference Summary

ES6+ Features

  • let/const - block scoped
  • Arrow functions - concise, lexical this
  • Template literals - string interpolation
  • Destructuring - unpack values
  • Spread/Rest - expand/collect
  • Classes - syntactic sugar
  • Modules - import/export

Execution Context

  • GEC - Global Execution Context
  • FEC - Function Execution Context
  • Creation Phase - memory allocation
  • Execution Phase - code runs
  • Call Stack - manages contexts

Event Loop

  • Call Stack - sync execution
  • Web APIs - async operations
  • Microtask Queue - Promises (priority)
  • Callback Queue - other callbacks
  • Event Loop - orchestrates all

Promises

  • States: pending, fulfilled, rejected
  • .then() - handle success
  • .catch() - handle errors
  • .finally() - cleanup
  • async/await - syntactic sugar

Scope & Hoisting

  • Global - accessible everywhere
  • Function - function scoped
  • Block - {} scoped (let/const)
  • var - hoisted, initialized undefined
  • let/const - hoisted, TDZ
  • Functions - fully hoisted

Callbacks

  • Function passed as argument
  • Executed later
  • Used in async operations
  • Higher-order functions
  • Callback hell - avoid with Promises