11 KiB
Lesson 00: Getting Started & Assessment Review
Duration: 45 minutes Objective: Understand JavaScript fundamentals and identify key areas for focused study
Introduction
Welcome to your JavaScript interview preparation curriculum! This lesson reviews the diagnostic assessment and establishes foundational knowledge that will be built upon in subsequent lessons.
Based on common evaluation results, most developers need focused review in:
- Type coercion and equality
- Closures and scope
- The
thiskeyword and context binding - Prototypes and inheritance
- Modern ES6+ syntax
- Asynchronous execution patterns
Part 1: JavaScript Type System Fundamentals
1.1 Primitive Types
JavaScript has 7 primitive types:
typeof undefined; // "undefined"
typeof true; // "boolean"
typeof 42; // "number"
typeof 9007199254740991n; // "bigint"
typeof "hello"; // "string"
typeof Symbol(); // "symbol"
typeof null; // "object" ⚠️ This is a bug in JavaScript!
The null Bug:
typeof null returning "object" is a historical bug that can't be fixed without breaking existing code. null represents the intentional absence of any object value.
// Checking for null correctly
const value = null;
console.log(value === null); // true
console.log(typeof value === "object" && value === null); // true
1.2 Reference Types
Objects, Arrays, and Functions are reference types:
typeof {}; // "object"
typeof []; // "object" (arrays are objects)
typeof function(){}; // "function"
Key Difference:
- Primitives are compared by value
- References are compared by reference (memory location)
// Primitives - value comparison
const a = 42;
const b = 42;
console.log(a === b); // true
// References - memory location comparison
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
console.log(arr1 === arr2); // false (different objects in memory)
console.log(arr1 === arr1); // true (same reference)
const arr3 = arr1;
console.log(arr3 === arr1); // true (same reference)
Part 2: Floating-Point Precision
2.1 The 0.1 + 0.2 Problem
JavaScript uses IEEE 754 double-precision floating-point format. Some decimal numbers cannot be represented exactly in binary.
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false ⚠️
Why?
- 0.1 in binary:
0.0001100110011...(repeating) - Computer must round, introducing tiny errors
- These errors accumulate during operations
Solutions:
// 1. Use epsilon comparison
function areClose(a, b, epsilon = 0.0001) {
return Math.abs(a - b) < epsilon;
}
console.log(areClose(0.1 + 0.2, 0.3)); // true
// 2. Use Number.EPSILON
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // true
// 3. Work with integers (convert to cents, etc.)
const price1 = 10; // 10 cents
const price2 = 20; // 20 cents
const total = price1 + price2; // 30 cents (exact)
// 4. Round to fixed decimals
const result = Math.round((0.1 + 0.2) * 100) / 100; // 0.3
Interview Tip: Always mention this caveat when working with money or precise calculations. Suggest using integers or decimal libraries.
Part 3: Var, Let, and Const
3.1 The Problem with var
// Function scope (not block scope)
function example() {
if (true) {
var x = 5;
}
console.log(x); // 5 (var leaks out of the block!)
}
// Hoisting
console.log(y); // undefined (not an error!)
var y = 10;
// What actually happens:
var y;
console.log(y); // undefined
y = 10;
The Classic Loop Problem:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Logs: 3, 3, 3
// Why? All callbacks share the same 'i' variable
// By the time they execute, the loop finished and i = 3
3.2 Let and Const (ES6+)
// Block scope
if (true) {
let x = 5;
const y = 10;
}
console.log(x); // ReferenceError
console.log(y); // ReferenceError
// No hoisting issues
console.log(z); // ReferenceError (temporal dead zone)
let z = 15;
// Loop with let creates a new binding per iteration
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Logs: 0, 1, 2 ✅
Const Rules:
const x = 10;
x = 20; // TypeError: Assignment to constant variable
// But objects are mutable!
const obj = { name: "Alice" };
obj.name = "Bob"; // ✅ Allowed (modifying property)
obj = {}; // ❌ TypeError (reassigning variable)
// Use Object.freeze() for immutability
const frozen = Object.freeze({ name: "Alice" });
frozen.name = "Bob"; // Silently fails (throws in strict mode)
console.log(frozen.name); // "Alice"
Best Practice: Use const by default, let when you need reassignment, avoid var.
Part 4: Array Behavior and Holes
4.1 Sparse Arrays
const arr = [1, 2, 3];
arr[10] = 11;
console.log(arr.length); // 11 (not 4!)
console.log(arr); // [1, 2, 3, empty × 7, 11]
console.log(arr[5]); // undefined (hole in array)
Array Length:
- Length is always the highest index + 1
- Creating holes doesn't initialize elements
const sparse = new Array(5);
console.log(sparse.length); // 5
console.log(sparse[0]); // undefined
console.log(0 in sparse); // false (hole, not undefined value)
const filled = [undefined, undefined];
console.log(0 in filled); // true (actual undefined value)
Array Methods and Holes:
const arr = [1, , 3]; // Array with hole
arr.forEach(x => console.log(x)); // 1, 3 (skips holes)
arr.map(x => x * 2); // [2, empty, 6] (preserves holes)
Array.from(arr); // [1, undefined, 3] (converts holes)
Part 5: Type Coercion Essentials
5.1 Truthy and Falsy Values
Falsy values (8 total):
if (false) {} // false
if (0) {} // 0
if (-0) {} // -0
if (0n) {} // 0n (BigInt zero)
if ("") {} // empty string
if (null) {} // null
if (undefined) {} // undefined
if (NaN) {} // NaN
Everything else is truthy, including:
if ("0") {} // truthy (non-empty string)
if ("false") {} // truthy
if ([]) {} // truthy (empty array)
if ({}) {} // truthy (empty object)
if (function(){}) {} // truthy
5.2 Unary Plus Operator
console.log(+"42"); // 42
console.log(+"3.14"); // 3.14
console.log(+"hello"); // NaN
console.log(+true); // 1
console.log(+false); // 0
console.log(+null); // 0
console.log(+undefined); // NaN
// Quick number conversion
const input = "123";
const num = +input; // Same as Number(input)
5.3 Addition Coercion
// String concatenation wins
console.log("" + 1 + 2); // "12" (1 converts to string first)
console.log(1 + 2 + ""); // "3" (addition happens first)
console.log("" + []); // "" (array becomes empty string)
console.log("" + {}); // "[object Object]"
// Arrays
console.log([] + []); // "" (both arrays convert to empty strings)
console.log([1] + [2]); // "12"
console.log([1, 2] + [3]); // "1,23"
Part 6: Essential Function Concepts
6.1 Function Declarations vs Expressions
// Declaration - hoisted
foo(); // ✅ Works
function foo() {
console.log("I'm hoisted!");
}
// Expression - not hoisted
bar(); // ❌ ReferenceError
const bar = function() {
console.log("I'm not hoisted!");
};
6.2 Arrow Functions Preview
Arrow functions have important differences (covered in Lesson 02):
// No 'this' binding
const obj = {
value: 42,
regularFunc: function() {
console.log(this.value); // 42
},
arrowFunc: () => {
console.log(this.value); // undefined (or global value)
}
};
obj.regularFunc(); // 42
obj.arrowFunc(); // undefined
Key Differences:
- Arrow functions inherit
thisfrom outer scope - Cannot be used as constructors
- No
argumentsobject - Cannot use
yield(not generators)
Part 7: Common Interview Gotchas
7.1 Object Property Duplicates
const obj = { a: 1, b: 2, a: 3 };
console.log(obj.a); // 3 (last value wins)
In modern JavaScript, duplicate keys are allowed. The last value overwrites previous ones.
7.2 Automatic Semicolon Insertion (ASI)
// This looks fine...
function getData() {
return
{
name: "Alice"
}
}
console.log(getData()); // undefined ⚠️
// JavaScript interprets it as:
function getData() {
return; // semicolon inserted!
{
name: "Alice"
}
}
// Fix: Keep opening brace on same line
function getData() {
return {
name: "Alice"
};
}
7.3 Implicit Global Variables
function oops() {
x = 10; // ⚠️ Creates global variable (no var/let/const)
}
oops();
console.log(x); // 10 (global!)
// Even worse:
let x = y = 10;
// This is really: let x = (y = 10)
// x is local, y is global!
function example() {
let x = y = 20;
}
example();
console.log(y); // 20 (global!)
Fix: Always use "use strict"; and declare all variables.
"use strict";
function safe() {
x = 10; // ReferenceError: x is not defined
}
Part 8: Preparing for Deep Dive Topics
Topics Covered in Upcoming Lessons
Lesson 01 - Type System & Coercion:
- Double equals vs triple equals
- Type conversion rules
- Advanced coercion scenarios
Lesson 02 - This Binding:
- How
thisis determined - Call, apply, and bind
- Arrow functions and
this
Lesson 03 - Closures:
- Lexical scope
- Practical closure patterns
- Memory implications
Lesson 04 - Event Loop:
- Call stack, task queue, microtask queue
- Understanding async execution order
Lesson 05 - Promises:
- Promise states and chaining
- Error handling
- Async/await patterns
Lesson 06 - Prototypes:
- Prototype chain
- Constructor functions vs classes
- Inheritance patterns
Lesson 07 - ES6+ Features:
- Destructuring
- Spread/rest operators
- Template literals, default parameters
Lesson 08 - Array Methods:
- Map, filter, reduce
- ForEach vs for loops
- Functional programming concepts
Key Takeaways
✅ Remember:
typeof nullreturns"object"(historical bug)- Never use
===with floating-point decimals varis function-scoped,let/constare block-scoped- Arrays are compared by reference, not value
- Use
constby default,letwhen needed, avoidvar - Arrow functions don't have their own
thisbinding - Array length = highest index + 1
- Always declare variables to avoid implicit globals
Practice Tips
- Run code examples - Don't just read them
- Predict output before running code
- Understand "why" - Memorization isn't enough
- Practice explaining concepts out loud
- Focus on weak areas identified in your evaluation
Next Steps
Complete the medium-difficulty quiz to test your understanding of these fundamentals. Then proceed to Lesson 01 to dive deeper into the type system.
Time to complete quiz: 10-15 minutes