Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › async await

JavaScript Interview Essentials: 20 Concepts You Should Explain Clearly

By Freedom251 Team · · 8 min read

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Strong JavaScript interview answers do two things: predict what a small program does and explain why. The 20 concepts below give you the mental models for both. They move from values and scope to functions, objects and asynchronous scheduling, with a short example, a common trap and an interview-ready explanation for each.

There is no official, universal list of exactly 20 “must-knows.” This is a practical set of language rules and host-runtime behavior that repeatedly helps candidates reason aloud without relying on memorized output.

As an Amazon Associate I earn from qualifying purchases.

Start with the synchronous foundations

Before discussing promises or event loops, make sure you can describe what JavaScript is evaluating right now. Values, bindings, scope and call sites determine most small-code questions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Primitive and object values

JavaScript values are commonly discussed as primitives and objects. Primitives include strings, numbers, bigints, booleans, symbols, null and undefined. Objects include arrays, functions, dates and ordinary object literals. A variable holds a value; with an object, that value is a reference to an object.

let a = { score: 1 };
let b = a;
b.score = 2;
console.log(a.score); // 2

Both variables refer to the same object. Assigning a primitive copies its value, while assigning an object copies the reference. In an interview, say explicitly whether the code changes a binding or mutates an object.

2. Strict equality and identity

=== compares without the type coercion performed by abstract equality. Primitive values of different types are not strictly equal, and objects compare by identity.

console.log(1 === "1"); // false
console.log({} === {}); // false
const item = {};
console.log(item === item); // true

Two separately created objects are different identities even when their properties look identical. Use === as the ordinary default, then explain that an object comparison is not a deep, structural comparison.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Abstract equality and coercion

== applies JavaScript’s abstract-equality algorithm, which can convert one operand before comparing.

console.log(0 == "0"); // true
console.log(false == 0); // true

The result is defined, but the implicit conversions can make an explanation harder to follow. If an interviewer asks about ==, describe the conversion rather than calling it “random”; if not, prefer the predictable behavior of ===.

4. var declarations

var is scoped to the containing function, or to the global script context when declared at top level in a script. A block such as if or for does not create a separate var binding.

function example() {
  if (true) {
    var message = "ready";
  }
  console.log(message); // "ready"
}
example();

The declaration is available throughout the function, although its assignment occurs where written. This function-level behavior is the source of many loop and callback surprises.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. let and const declarations

let and const are block scoped. A let binding may be reassigned; a const binding may not be reassigned after initialization. const does not make an object immutable.

const settings = { dark: false };
settings.dark = true; // allowed
// settings = {};      // TypeError

The binding is fixed, while the object it references can still be mutated. Prefer these declarations when you want the block boundary and clearer reassignment rules.

6. Lexical scope

Lexical scope is determined by where code is written, not by which function happens to call it. An inner block can read bindings from surrounding blocks; an outer block cannot read a name declared only inside the inner block.

const outside = "A";
function show() {
  const inside = "B";
  console.log(outside, inside);
}
show();
// console.log(inside); // ReferenceError

When answering “what is accessible here?”, trace outward through the written nesting structure and stop at the first matching binding.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

7. Hoisting and the temporal dead zone

Hoisting is a useful description of declaration instantiation and the access behavior it creates; JavaScript does not literally move source lines. A var binding is initialized to undefined before execution reaches its assignment. A let or const binding exists from the start of its scope but cannot be accessed until its declaration is evaluated. That interval is the temporal dead zone.

console.log(v); // undefined
var v = 3;

console.log(n); // ReferenceError
let n = 3;

Function declarations have their own initialization behavior, while a function expression assigned to a variable follows that variable’s rules. Explain the observable result rather than claiming every declaration is treated identically.

8. Function call forms

A function’s call form affects its behavior, especially this. These are different calls:

run();
obj.run();
new Run();
run.call(obj);

The first is a plain call, the second supplies obj as a receiver, new creates a construction call, and call explicitly supplies a receiver. When an output depends on a function, identify the call syntax before reading the body.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

9. Closures

MDN Web Docs defines a closure as “the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).” A returned or scheduled function can therefore continue to access bindings from the scope where it was created, even after the outer function has returned.

function makeCounter() {
  let count = 0;
  return () => ++count;
}
const next = makeCounter();
console.log(next()); // 1
console.log(next()); // 2

The closure preserves access to the binding, not a magical snapshot of every value. If the binding changes, later calls observe the current value. This is useful for callbacks and private state. A classic loop bug occurs when several callbacks close over one function-scoped var binding; block-scoped per-iteration bindings avoid that shared binding.

10. this in ordinary functions

For a regular function, this is determined by the call site, not by where the function was defined.

const user = {
  name: "Mina",
  greet() { return this.name; }
};
console.log(user.greet()); // "Mina"
const detached = user.greet;
console.log(detached()); // receiver-dependent; often undefined in strict mode

Calling through user.greet() supplies user. Storing the function and calling it plainly removes that receiver. Strict mode and the host environment affect the plain-call result, so state those conditions when needed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

11. Arrow functions and lexical this

Arrow functions do not create their own this. They read the value from the surrounding lexical scope.

const timer = {
  value: 7,
  start() {
    setTimeout(() => console.log(this.value), 0);
  }
};

The arrow keeps the this from start. That makes arrows useful for callbacks that should retain a surrounding receiver, but unsuitable when a method needs a dynamically supplied receiver of its own.

12. Prototype-based property lookup

Every ordinary object can have a prototype object. If a property is not found among an object’s own properties, lookup can continue through the prototype chain.

const vehicle = { moves: true };
const bike = Object.create(vehicle);
bike.wheels = 2;
console.log(bike.wheels); // own property
console.log(bike.moves);  // inherited property

“Own” and “inherited” are different facts. A property may be readable through the chain without being stored directly on the object. This delegation model is part of JavaScript itself.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

13. Class syntax

class provides a familiar authoring syntax for constructor functions and prototype methods; it does not replace the prototype object model.

Rank #4
Sale
JavaScript: The Definitive Guide
  • Used Book in Good Condition
class User {
  constructor(name) { this.name = name; }
  greet() { return `Hi ${this.name}`; }
}
const user = new User("Mina");

The greet method is placed on User.prototype, so instances can find it through their prototype chain. In an interview, distinguish the surface syntax from the underlying delegation behavior.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Promises and asynchronous control flow

Asynchronous code adds a second question: when does work finish, and how is its result delivered? Promises provide the representation; async/await provide a readable control-flow style.

14. Promise states

A promise represents a result that may be pending, fulfilled or rejected. Once fulfilled or rejected, it is settled and cannot switch to the other outcome.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const result = fetchData();
result.then(value => {
  console.log(value);
}).catch(error => {
  console.error(error);
});

then registers fulfillment work and returns another promise, allowing operations to be composed. catch handles rejection in the chain. A promise is not the data itself; it is an object representing the eventual outcome.

15. Promise chaining and returned values

Each then callback determines the next promise’s result. Returning a plain value fulfills the next promise with that value; returning another promise adopts its eventual state. Throwing creates a rejection.

getUser()
  .then(user => getOrders(user.id))
  .then(orders => orders.length)
  .then(count => console.log(count))
  .catch(error => console.error(error));

Returning the inner operation is essential. If you omit that return, later handlers can run before the nested work finishes and receive undefined.

16. Async functions

An async function always returns a new promise. Returning a non-promise value fulfills that promise with the value; throwing rejects it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
async function answer() {
  return 42;
}
answer().then(value => console.log(value)); // 42

This rule means callers must handle an async function as a promise even when its body appears to return synchronously.

17. await and error handling

await unwraps an awaited result inside an async function and suspends the rest of that function until the result settles. It does not stop the surrounding JavaScript agent.

async function load() {
  try {
    const response = await request();
    return response.data;
  } catch (error) {
    console.error("Request failed", error);
  }
}

A rejection behaves like a thrown error at the await point, so ordinary try/catch can handle it. Code outside load can continue while the request is pending.

18. Sequential versus concurrent awaits

Where you place await determines when operations start. This is sequential:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const first = await readFirst();
const second = await readSecond();

readSecond is not started until the first result arrives. If the operations are independent, start them before awaiting:

const firstPromise = readFirst();
const secondPromise = readSecond();
const [first, second] = await Promise.all([firstPromise, secondPromise]);

The second form allows independent work to proceed concurrently and makes the intended coordination explicit.

19. Promise.all and Promise.allSettled

Promise.all fulfills with an array of values when every input fulfills, and rejects when any input rejects. Use it when one failure should fail the combined operation. Promise.allSettled waits for every input and reports each fulfillment or rejection, which is useful when you need a complete results report.

const outcomes = await Promise.allSettled([
  checkPrimary(),
  checkBackup()
]);

Do not casually write separate awaits for promises that were created together when you need coordinated failure handling. Keeping the promises in a combinator makes the policy visible.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How JavaScript schedules work

20. Call stack, execution contexts, tasks and microtasks

The JavaScript engine runs active code on a call stack, creating execution contexts for global code and function calls. A browser or other host supplies APIs such as timers and networking; those APIs are not the JavaScript language itself.

After the current stack empties, queued work can run. In browser-oriented event-loop explanations, microtasks—such as promise reactions—are drained before the host takes another task, such as a timer callback. Exact scheduling details are host-defined, so do not present one browser diagram as a universal rule for every runtime.

console.log("A");
setTimeout(() => console.log("timer"), 0);
Promise.resolve().then(() => console.log("promise"));
console.log("B");

The synchronous logs print first: A, then B. Once the stack is empty, the promise reaction runs as a microtask, followed by the timer task in the usual browser model: promise, then timer. The useful explanation names each queue instead of saying “async code runs later.”

A practical interview practice routine

  1. Predict before running. Write down the output, thrown error or unresolved value.
  2. Mark bindings and receivers. Identify each scope, whether a declaration is initialized, and what object—if any—supplies this.
  3. Trace references. For objects, distinguish mutation from reassignment and follow prototype lookup when a property is missing.
  4. Trace asynchronous boundaries. Separate synchronous statements, promise reactions, timers and host callbacks.
  5. State the caveat. Mention strict mode, host-specific scheduling or concurrency assumptions when they affect the answer.
  6. Give a one-sentence verdict. For example: “The arrow captures the method’s receiver, the promise reaction is a microtask, and the timer runs afterward in this browser scheduling model.”

That routine turns a code-puzzle answer into the kind of reasoning interviewers can evaluate: a predicted result supported by the language rule and the relevant runtime qualification.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

async awaitClosuresevent loopJavaScriptJavaScript interviewPromisesscopeWeb development

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.