JavaScript Basics — Study & Interview Revision Notes
1. Variables: var, let, const
Key Differences
Feature var let const
Scope Function-scoped Block-scoped Block-scoped
Redeclaration Allowed Not allowed Not allowed
Reassignment Allowed Allowed Not allowed
Hoisted, initialized as Hoisted, but in "Temporal Hoisted, but in "Temporal
Hoisting
undefined Dead Zone" Dead Zone"
Global object Yes (attaches to
No No
property window)
Examples
javascript
// var is function-scoped, not block-scoped
function testVar() {
if (true) {
var x = 10;
[Link](x); // 10 (accessible outside the if block)
function testLet() {
if (true) {
let y = 20;
[Link](y); // ReferenceError: y is not defined
javascript
// Redeclaration
var a = 1;
var a = 2; // fine
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
javascript
// const doesn't mean "immutable value", it means "immutable binding"
const obj = { name: "John" };
[Link] = "Doe"; // allowed, object contents can change
obj = {}; // TypeError: Assignment to constant variable
⭐ Interview Tip
"const prevents reassignment of the variable, not mutation of the object it points to." This is a classic
interview trap question — be ready to explain it with an object/array example.
Classic Loop Closure Question (asked A LOT)
javascript
// var - all callbacks share the same variable
for (var i = 0; i < 3; i++) {
setTimeout(() => [Link](i), 100);
// Output: 3 3 3
// let - each iteration gets a new binding
for (let i = 0; i < 3; i++) {
setTimeout(() => [Link](i), 100);
// Output: 0 1 2
Why: var has function scope, so all three setTimeout callbacks reference the same i (which is 3 by the
time they run). let creates a new block-scoped i for each loop iteration.
2. Data Types (Primitive vs Reference)
Primitive Types (stored by value)
string, number, boolean, null, undefined, symbol, bigint
Reference Types (stored by reference)
object, array, function
Examples
javascript
// Primitive - copied by value
let a = 10;
let b = a;
b = 20;
[Link](a); // 10 (unaffected)
javascript
// Reference - copied by reference
let obj1 = { value: 10 };
let obj2 = obj1;
[Link] = 20;
[Link]([Link]); // 20 (both point to same object in memory)
typeof Quirks (frequently asked)
javascript
typeof "hello"; // "string"
typeof 42; // "number"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" ⚠️famous JS bug (kept for backward compatibility)
typeof Symbol(); // "symbol"
typeof 10n; // "bigint"
typeof function(){}; // "function"
typeof []; // "object"
typeof {}; // "object"
⭐ Interview Tip
"Why does typeof null === 'object'?" This is a legacy bug in JS from its first implementation — null
was represented internally with the same tag as objects. It's kept for backward compatibility.
3. Operators, Type Coercion, == vs ===
Type Coercion
JavaScript automatically converts types when operators expect a specific type.
javascript
"5" + 3; // "53" (number converted to string)
"5" - 3; // 2 (string converted to number)
"5" * "2"; // 10
true + 1; // 2 (true → 1)
false + 1; // 1
"" + null; // "null"
1 + undefined;// NaN
== (loose equality) vs === (strict equality)
javascript
0 == "0"; // true (type coercion happens)
0 === "0"; // false (different types)
null == undefined; // true
null === undefined; // false
NaN == NaN; // false (NaN is never equal to anything, even itself)
NaN === NaN; // false
⭐ Interview Tip
Always prefer === unless you have an explicit reason to allow type coercion. Interviewers often ask
you to explain why == is risky — give the 0 == "0" and null == undefined examples.
Checking for NaN properly
javascript
[Link](NaN); // true (correct way)
isNaN("hello"); // true (misleading, coerces first)
[Link]("hello"); // false (no coercion, safer)
4. Conditionals & Loops
Conditionals
javascript
// if / else
if (age >= 18) {
[Link]("Adult");
} else if (age >= 13) {
[Link]("Teen");
} else {
[Link]("Child");
// switch
switch (day) {
case "Mon":
[Link]("Monday");
break;
default:
[Link]("Unknown day");
// Ternary
const status = age >= 18 ? "Adult" : "Minor";
Loops
javascript
// for loop
for (let i = 0; i < 5; i++) [Link](i);
// while
let i = 0;
while (i < 5) {
[Link](i);
i++;
}
// do-while (executes at least once)
let j = 0;
do {
[Link](j);
j++;
} while (j < 5);
// for...of (iterates over VALUES - arrays, strings, maps, sets)
for (const val of [10, 20, 30]) [Link](val);
// for...in (iterates over KEYS - objects, arrays)
const obj = { a: 1, b: 2 };
for (const key in obj) [Link](key, obj[key]);
⭐ Interview Tip
for...of vs for...in
for...of → iterates values, used with iterables (arrays, strings, Maps, Sets)
for...in → iterates keys/indices, used with objects (also works on arrays but not
recommended — it includes inherited enumerable properties too)
javascript
const arr = [10, 20, 30];
[Link] = "hello";
for (const i in arr) [Link](i);
// "0" "1" "2" "customProp" ⚠️includes extra property
for (const v of arr) [Link](v);
// 10 20 30 ✅ only array values
5. Functions (Declarations, Expressions, Arrow Functions)
Function Declaration
javascript
function greet(name) {
return `Hello, ${name}`;
Hoisted fully — can be called before its definition in the code.
javascript
greet("Sam"); // works even before declaration due to hoisting
function greet(name) { return `Hi ${name}`; }
Function Expression
javascript
const greet = function (name) {
return `Hello, ${name}`;
};
Not hoisted with its definition — only the variable declaration is hoisted (as undefined for
var).
javascript
greet("Sam"); // TypeError: greet is not a function
var greet = function (name) { return `Hi ${name}`; };
Arrow Functions
javascript
const greet = (name) => `Hello, ${name}`;
Key Differences: Arrow vs Regular Functions
Feature Regular Function Arrow Function
Own this (depends on how it's Inherits this from enclosing scope
this binding
called) (lexical)
arguments object Available Not available
Used as constructor
Yes No (throws error)
(new)
Hoisting Fully hoisted (declarations) Not hoisted (like expressions)
this Example (VERY common interview question)
javascript
const obj = {
name: "Alice",
regularFn: function () {
[Link]([Link]); // "Alice" - this = obj
},
arrowFn: () => {
[Link]([Link]); // undefined - this = enclosing (global) scope
};
[Link](); // "Alice"
[Link](); // undefined
Practical Case: Arrow functions fixing this in callbacks
javascript
function Timer() {
[Link] = 0;
setInterval(function () {
[Link]++; // 'this' here refers to global/undefined, NOT Timer instance ❌
}, 1000);
function TimerFixed() {
[Link] = 0;
setInterval(() => {
[Link]++; // arrow function inherits 'this' from TimerFixed ✅
}, 1000);
⭐ Interview Tip
Arrow functions are commonly used in callbacks (e.g., inside class methods or timers) specifically
because they don't create their own this — they inherit it from the surrounding lexical scope.
6. Template Literals
javascript
const name = "Alice";
const age = 25;
// Old way
[Link]("My name is " + name + " and I am " + age + " years old.");
// Template literal way
[Link](`My name is ${name} and I am ${age} years old.`);
Features
Multi-line strings
javascript
const message = `Line 1
Line 2
Line 3`;
Expression evaluation inside ${}
javascript
const a = 5, b = 10;
[Link](`Sum is ${a + b}`); // "Sum is 15"
Tagged templates (advanced, sometimes asked)
javascript
function tag(strings, ...values) {
[Link](strings); // array of string parts
[Link](values); // array of interpolated values
return "Custom output";
const result = tag`Hello ${name}, you are ${age} years old`;
[Link](result); // "Custom output"
⭐ Interview Tip
Template literals are preferred over string concatenation for readability, multi-line support, and
embedding expressions directly.
🔑 Quick Revision Checklist
Explain var vs let vs const with hoisting + scope example
Explain the classic var vs let loop closure question
Explain primitive vs reference types with a mutation example
Explain typeof null === "object" bug
Explain == vs === with 0 == "0" example
Explain for...in vs for...of
Explain function hoisting differences (declaration vs expression)
Explain arrow function this behavior with an object method example
Explain template literals and tagged templates