What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
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.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minute1. 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.
#1 Best Overall
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.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →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.
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.
Rank #2
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.
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.
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.
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.
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
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.
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.
Recommended Free Tools
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.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →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.
Best Value
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:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteconst 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.
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
- Predict before running. Write down the output, thrown error or unresolved value.
- Mark bindings and receivers. Identify each scope, whether a declaration is initialized, and what object—if any—supplies
this. - Trace references. For objects, distinguish mutation from reassignment and follow prototype lookup when a property is missing.
- Trace asynchronous boundaries. Separate synchronous statements, promise reactions, timers and host callbacks.
- State the caveat. Mention strict mode, host-specific scheduling or concurrency assumptions when they affect the answer.
- 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.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteQuick Recap
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.

