<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Notes by Maaz]]></title><description><![CDATA[Notes by Maaz]]></description><link>https://maazzz.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 18 Sep 2026 02:42:01 GMT</lastBuildDate><atom:link href="https://maazzz.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[JavaScript Spread vs Rest Operators: ... Explained Simply]]></title><description><![CDATA[JavaScript has a syntax that looks deceptively simple:
...

You may have seen it used with arrays, objects, function parameters, or destructuring.
But here's the confusing part:
The same ... syntax ca]]></description><link>https://maazzz.hashnode.dev/javascript-spread-vs-rest-operators-explained-simply</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-spread-vs-rest-operators-explained-simply</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Fri, 04 Sep 2026 20:13:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/1c42e2b2-dcec-439d-b30b-78ef53dc670a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript has a syntax that looks deceptively simple:</p>
<pre><code class="language-js">...
</code></pre>
<p>You may have seen it used with arrays, objects, function parameters, or destructuring.</p>
<p>But here's the confusing part:</p>
<p><strong>The same</strong> <code>...</code> <strong>syntax can do two completely different things.</strong></p>
<p>It can <strong>spread</strong> values out:</p>
<pre><code class="language-js">const numbers = [1, 2, 3];

console.log(...numbers);
</code></pre>
<p>Or it can <strong>collect</strong> values together:</p>
<pre><code class="language-js">function sum(...numbers) {
  console.log(numbers);
}
</code></pre>
<p>So what's the difference?</p>
<p>The easiest way to remember it is:</p>
<blockquote>
<p><strong>Spread expands. Rest collects.</strong></p>
</blockquote>
<p>Once you understand that idea, the rest becomes much easier.</p>
<hr />
<h2>What Is the Spread Operator?</h2>
<p>The <strong>spread operator</strong> uses <code>...</code> to expand the elements of an iterable or the properties of an object into another context.</p>
<p>Think of it as:</p>
<pre><code class="language-text">Array
[1, 2, 3]
     ↓
   spread
     ↓
1   2   3
</code></pre>
<p>For example:</p>
<pre><code class="language-js">const numbers = [1, 2, 3];

console.log(...numbers);
</code></pre>
<p>Instead of treating <code>numbers</code> as one array value, spread expands its elements.</p>
<p>The result is conceptually:</p>
<pre><code class="language-text">1 2 3
</code></pre>
<p>The same idea becomes especially useful when creating new arrays or objects.</p>
<hr />
<h2>Spread With Arrays</h2>
<h3>Copying an Array</h3>
<p>You can create a shallow copy of an array using spread:</p>
<pre><code class="language-js">const original = [1, 2, 3];

const copy = [...original];

console.log(copy);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">[1, 2, 3]
</code></pre>
<p>Now <code>copy</code> is a different array:</p>
<pre><code class="language-js">console.log(original === copy);
</code></pre>
<pre><code class="language-text">false
</code></pre>
<p>This is useful when you want a new array instead of modifying the original reference.</p>
<hr />
<h3>Combining Arrays</h3>
<p>Spread makes combining arrays very readable.</p>
<p>Without spread, you might use methods such as <code>concat()</code>:</p>
<pre><code class="language-js">const first = [1, 2];
const second = [3, 4];

const combined = first.concat(second);
</code></pre>
<p>With spread:</p>
<pre><code class="language-js">const first = [1, 2];
const second = [3, 4];

const combined = [...first, ...second];

console.log(combined);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">[1, 2, 3, 4]
</code></pre>
<p>You can even add new values between them:</p>
<pre><code class="language-js">const combined = [0, ...first, 2.5, ...second, 5];
</code></pre>
<p>Result:</p>
<pre><code class="language-text">[0, 1, 2, 2.5, 3, 4, 5]
</code></pre>
<p>This is one of the most common practical uses of the spread operator.</p>
<hr />
<h2>Spread With Function Arguments</h2>
<p>Spread can also expand an array into individual function arguments.</p>
<p>Consider:</p>
<pre><code class="language-js">const numbers = [10, 20, 30];

Math.max(...numbers);
</code></pre>
<p>It's conceptually similar to:</p>
<pre><code class="language-js">Math.max(10, 20, 30);
</code></pre>
<p>Without spread:</p>
<pre><code class="language-js">Math.max(numbers);
</code></pre>
<p>you're passing the entire array as one argument.</p>
<p>With spread:</p>
<pre><code class="language-js">Math.max(...numbers);
</code></pre>
<p>the array's elements become separate arguments.</p>
<p>Think:</p>
<pre><code class="language-text">[10, 20, 30]
     ↓
   spread
     ↓
10, 20, 30
     ↓
Math.max(10, 20, 30)
</code></pre>
<hr />
<h2>Spread With Objects</h2>
<p>Spread isn't limited to arrays.</p>
<p>You can also spread an object's properties into another object.</p>
<pre><code class="language-js">const user = {
  name: "Maaz",
  role: "Developer"
};

const updatedUser = {
  ...user
};
</code></pre>
<p>Now <code>updatedUser</code> contains the same properties.</p>
<p>You can also add or override properties:</p>
<pre><code class="language-js">const updatedUser = {
  ...user,
  role: "Senior Developer",
  active: true
};
</code></pre>
<p>Result:</p>
<pre><code class="language-js">{
  name: "Maaz",
  role: "Senior Developer",
  active: true
}
</code></pre>
<p>This is extremely useful when working with application state and structured data.</p>
<hr />
<h2>Merging Objects</h2>
<p>Spread provides a simple way to combine objects:</p>
<pre><code class="language-js">const user = {
  name: "Maaz"
};

const preferences = {
  theme: "dark",
  notifications: true
};

const profile = {
  ...user,
  ...preferences
};
</code></pre>
<p>Result:</p>
<pre><code class="language-js">{
  name: "Maaz",
  theme: "dark",
  notifications: true
}
</code></pre>
<p>If properties have the same key, the later value wins:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",
  role: "Developer"
};

const update = {
  role: "Designer"
};

const result = {
  ...user,
  ...update
};
</code></pre>
<p>Result:</p>
<pre><code class="language-text">role → "Designer"
</code></pre>
<p>The order matters.</p>
<hr />
<h2>What Is the Rest Operator?</h2>
<p>Now we come to the other side of <code>...</code>.</p>
<p>The <strong>rest operator</strong> collects multiple values into a single array.</p>
<p>Think of it as the opposite mental action:</p>
<pre><code class="language-text">1   2   3   4
 \   |   |  /
      rest
        ↓
 [1, 2, 3, 4]
</code></pre>
<p>For example:</p>
<pre><code class="language-js">function sum(...numbers) {
  console.log(numbers);
}

sum(10, 20, 30);
</code></pre>
<p>Inside the function:</p>
<pre><code class="language-text">numbers → [10, 20, 30]
</code></pre>
<p>The rest parameter collects all remaining arguments into an array.</p>
<hr />
<h2>Rest Parameters in Functions</h2>
<p>This becomes particularly useful when you don't know how many arguments a function will receive.</p>
<pre><code class="language-js">function sum(...numbers) {
  return numbers.reduce((total, number) =&gt; total + number, 0);
}

console.log(sum(10, 20));
console.log(sum(10, 20, 30, 40));
</code></pre>
<p>The function can accept any number of arguments.</p>
<p>Conceptually:</p>
<pre><code class="language-text">sum(10, 20)
       ↓
numbers = [10, 20]

sum(10, 20, 30, 40)
       ↓
numbers = [10, 20, 30, 40]
</code></pre>
<p>This is a common and practical use of rest parameters.</p>
<hr />
<h2>Rest With Destructuring</h2>
<p>Rest can also collect the remaining elements during array destructuring.</p>
<pre><code class="language-js">const numbers = [10, 20, 30, 40];

const [first, second, ...remaining] = numbers;

console.log(first);
console.log(second);
console.log(remaining);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">10
20
[30, 40]
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>first</code> gets <code>10</code></p>
</li>
<li><p><code>second</code> gets <code>20</code></p>
</li>
<li><p><code>remaining</code> collects everything left</p>
</li>
</ul>
<p>Think:</p>
<pre><code class="language-text">[10, 20, 30, 40]
 ↓   ↓    \_____/
first second remaining
</code></pre>
<hr />
<h2>Rest With Object Destructuring</h2>
<p>The same concept works with objects.</p>
<pre><code class="language-js">const user = {
  name: "Maaz",
  age: 20,
  city: "Multan"
};

const { name, ...details } = user;

console.log(name);
console.log(details);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Maaz

{
  age: 20,
  city: "Multan"
}
</code></pre>
<p><code>name</code> is extracted separately, while <code>...details</code> collects the remaining properties.</p>
<p>This pattern is particularly useful when you want to separate one or two properties from the rest of an object.</p>
<hr />
<h2>Spread vs Rest: What's the Difference?</h2>
<p>The syntax is the same:</p>
<pre><code class="language-js">...
</code></pre>
<p>But the <strong>job is different</strong>.</p>
<h3>Spread</h3>
<p><strong>Expands</strong> values.</p>
<pre><code class="language-js">const numbers = [1, 2, 3];

const copy = [...numbers];
</code></pre>
<p>Think:</p>
<pre><code class="language-text">[1, 2, 3]
    ↓
expand
    ↓
1, 2, 3
</code></pre>
<h3>Rest</h3>
<p><strong>Collects</strong> values.</p>
<pre><code class="language-js">function show(...numbers) {
  console.log(numbers);
}
</code></pre>
<p>Think:</p>
<pre><code class="language-text">1, 2, 3
  ↓
collect
  ↓
[1, 2, 3]
</code></pre>
<h3>The easiest rule</h3>
<blockquote>
<p><strong>Spread takes something together and spreads it out. Rest takes multiple things and gathers them together.</strong></p>
</blockquote>
<hr />
<h2>Why Does the Same <code>...</code> Mean Different Things?</h2>
<p>Because JavaScript determines its role from <strong>where it appears</strong>.</p>
<p>For example:</p>
<pre><code class="language-js">const copy = [...numbers];
</code></pre>
<p>Here, <code>...numbers</code> is expanding the array.</p>
<p>But:</p>
<pre><code class="language-js">function show(...numbers) {}
</code></pre>
<p>Here, <code>...numbers</code> is collecting function arguments.</p>
<p>And:</p>
<pre><code class="language-js">const [first, ...rest] = numbers;
</code></pre>
<p>Here, <code>...rest</code> collects the remaining elements.</p>
<p>So don't try to memorize separate symbols.</p>
<p>Instead, ask:</p>
<blockquote>
<p><strong>Is</strong> <code>...</code> <strong>expanding something or collecting the remaining values?</strong></p>
</blockquote>
<hr />
<h2>Practical Use Cases</h2>
<h3>1. Adding Items Without Mutating the Original Array</h3>
<pre><code class="language-js">const users = ["Ali", "Sara"];

const updatedUsers = [...users, "Ahmed"];
</code></pre>
<p>The original array remains unchanged.</p>
<p>This pattern is common when working with application state.</p>
<hr />
<h3>2. Updating Objects</h3>
<p>Instead of changing the original object:</p>
<pre><code class="language-js">user.role = "Admin";
</code></pre>
<p>you can create an updated object:</p>
<pre><code class="language-js">const updatedUser = {
  ...user,
  role: "Admin"
};
</code></pre>
<p>This is especially common in React and other state-management patterns where creating new values is useful.</p>
<hr />
<h3>3. Combining Data</h3>
<pre><code class="language-js">const frontend = ["HTML", "CSS", "JavaScript"];
const backend = ["Node.js", "PostgreSQL"];

const skills = [...frontend, ...backend];
</code></pre>
<p>Result:</p>
<pre><code class="language-text">["HTML", "CSS", "JavaScript", "Node.js", "PostgreSQL"]
</code></pre>
<hr />
<h3>4. Handling Flexible Function Arguments</h3>
<pre><code class="language-js">function average(...numbers) {
  const total = numbers.reduce((sum, n) =&gt; sum + n, 0);

  return total / numbers.length;
}

console.log(average(10, 20, 30));
</code></pre>
<p>Rest makes the function flexible without manually dealing with <code>arguments</code>.</p>
<hr />
<h3>5. Extracting What You Need</h3>
<p>Rest with destructuring can make object handling cleaner:</p>
<pre><code class="language-js">const user = {
  id: 101,
  name: "Maaz",
  email: "maaz@example.com",
  role: "Developer"
};

const { id, ...userData } = user;
</code></pre>
<p>Now:</p>
<pre><code class="language-text">id       → 101

userData → {
  name,
  email,
  role
}
</code></pre>
<p>This is useful when you need to separate specific properties from the remaining data.</p>
<hr />
<h2>One Important Detail: Spread Creates Shallow Copies</h2>
<p>When you write:</p>
<pre><code class="language-js">const copy = { ...user };
</code></pre>
<p>or:</p>
<pre><code class="language-js">const copy = [...users];
</code></pre>
<p>you're creating a <strong>shallow copy</strong>.</p>
<p>For simple values, this often behaves exactly as expected.</p>
<p>But nested objects are still referenced:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",
  address: {
    city: "Multan"
  }
};

const copy = { ...user };
</code></pre>
<p><code>copy.address</code> still refers to the same nested object as <code>user.address</code>.</p>
<p>So spread is not a deep-cloning mechanism.</p>
<p>For beginner-level usage, the important takeaway is simply:</p>
<blockquote>
<p><strong>Spread creates a new outer array or object, but nested objects are not automatically cloned.</strong></p>
</blockquote>
<hr />
<h2>Spread vs Rest Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Spread</th>
<th>Rest</th>
</tr>
</thead>
<tbody><tr>
<td>Main purpose</td>
<td>Expand values</td>
<td>Collect values</td>
</tr>
<tr>
<td>Mental model</td>
<td>Expand</td>
<td>Gather</td>
</tr>
<tr>
<td>Common with</td>
<td>Arrays, objects, function arguments</td>
<td>Function parameters, destructuring</td>
</tr>
<tr>
<td>Result</td>
<td>Individual values/properties</td>
<td>Array or collected properties</td>
</tr>
<tr>
<td>Example</td>
<td><code>[...items]</code></td>
<td><code>(...items)</code></td>
</tr>
</tbody></table>
<hr />
<h2>Final Takeaway</h2>
<p>The <code>...</code> syntax becomes much less confusing once you stop thinking of it as two unrelated features.</p>
<p>Remember one simple idea:</p>
<pre><code class="language-text">SPREAD
  ↓
Expand

[1, 2, 3]
    ↓
1, 2, 3
</code></pre>
<pre><code class="language-text">REST
  ↓
Collect

1, 2, 3
  ↓
[1, 2, 3]
</code></pre>
<p>From there, the common patterns become easy to recognize:</p>
<pre><code class="language-js">// Spread
const copy = [...items];

const merged = {
  ...user,
  ...preferences
};

// Rest
function sum(...numbers) {}

const [first, ...remaining] = numbers;

const { name, ...details } = user;
</code></pre>
<p>So whenever you see <code>...</code>, ask one question:</p>
<blockquote>
<p><strong>Is JavaScript spreading values out, or collecting the remaining values together?</strong></p>
</blockquote>
<p>If it's <strong>expanding</strong>, it's spread.</p>
<p>If it's <strong>collecting</strong>, it's rest.</p>
<p>That's the core concept behind one of the most useful pieces of modern JavaScript syntax.</p>
]]></content:encoded></item><item><title><![CDATA[Error Handling in JavaScript: Try, Catch, Finally Explained]]></title><description><![CDATA[Your JavaScript code can be perfectly valid and still fail while running.
For example:
const user = null;

console.log(user.name);

The code is syntactically valid, but JavaScript throws a runtime err]]></description><link>https://maazzz.hashnode.dev/error-handling-in-javascript-try-catch-finally-explained</link><guid isPermaLink="true">https://maazzz.hashnode.dev/error-handling-in-javascript-try-catch-finally-explained</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Thu, 03 Sep 2026 20:47:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/65f27e6a-1a57-4cea-819d-4e680de5591c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Your JavaScript code can be perfectly valid and still fail while running.</p>
<p>For example:</p>
<pre><code class="language-js">const user = null;

console.log(user.name);
</code></pre>
<p>The code is syntactically valid, but JavaScript throws a runtime error because you cannot access <code>name</code> from <code>null</code>.</p>
<p>Another example:</p>
<pre><code class="language-js">const result = JSON.parse("invalid json");
</code></pre>
<p>This also fails while the program is running.</p>
<p>Errors are a normal part of software development.</p>
<p>The important question isn't:</p>
<blockquote>
<p><strong>"How do I make sure errors never happen?"</strong></p>
</blockquote>
<p>It's:</p>
<blockquote>
<p><strong>"What should my program do when an error happens?"</strong></p>
</blockquote>
<p>That's where JavaScript's error-handling tools become important.</p>
<hr />
<h2>What Is an Error in JavaScript?</h2>
<p>An error is a problem that occurs while JavaScript is executing code.</p>
<p>For example:</p>
<pre><code class="language-js">console.log(userName);
</code></pre>
<p>If <code>userName</code> hasn't been defined, JavaScript throws a <code>ReferenceError</code>.</p>
<p>Common JavaScript errors include:</p>
<ul>
<li><p><code>ReferenceError</code> — trying to use something that doesn't exist</p>
</li>
<li><p><code>TypeError</code> — performing an invalid operation on a value</p>
</li>
<li><p><code>SyntaxError</code> — invalid JavaScript syntax</p>
</li>
<li><p><code>RangeError</code> — using a value outside an allowed range</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-js">const number = 10;

number.toUpperCase();
</code></pre>
<p>This causes a <code>TypeError</code> because <code>toUpperCase()</code> is a string method, not a number method.</p>
<hr />
<h2>What Happens When an Error Isn't Handled?</h2>
<p>Consider:</p>
<pre><code class="language-js">console.log("Start");

const user = null;
console.log(user.name);

console.log("End");
</code></pre>
<p>Once JavaScript encounters the error, normal execution stops at that point.</p>
<p>So <code>"End"</code> isn't printed.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Start
  ↓
Error occurs
  ↓
Execution stops
</code></pre>
<p>For a small script, this might simply produce an error in the console.</p>
<p>In a real application, an unhandled error could cause a feature to fail, leave the user confused, or prevent important cleanup code from running.</p>
<p>This is why applications need <strong>graceful failure</strong>.</p>
<p>Instead of letting an error unexpectedly break a flow, we can detect it and decide what should happen next.</p>
<hr />
<h2><code>try</code> and <code>catch</code></h2>
<p>JavaScript provides <code>try</code> and <code>catch</code> for handling errors.</p>
<pre><code class="language-js">try {
  // Code that might fail
} catch (error) {
  // Handle the error
}
</code></pre>
<p>For example:</p>
<pre><code class="language-js">try {
  const user = null;
  console.log(user.name);
} catch (error) {
  console.log("Something went wrong");
}
</code></pre>
<p>Instead of the error escaping and stopping this flow, the <code>catch</code> block gets control.</p>
<p>The basic flow is:</p>
<pre><code class="language-text">try
 │
 │ Code runs
 │
 ├── No error ─────────→ Continue
 │
 └── Error ────────────→ catch
</code></pre>
<p>The <code>catch</code> block receives the error that was thrown.</p>
<hr />
<h2>Understanding the <code>error</code> Object</h2>
<p>The value received by <code>catch</code> usually provides useful information about what went wrong.</p>
<pre><code class="language-js">try {
  const user = null;
  console.log(user.name);
} catch (error) {
  console.log(error.name);
  console.log(error.message);
}
</code></pre>
<p>For example, you might see:</p>
<pre><code class="language-text">TypeError
Cannot read properties of null
</code></pre>
<p>You can also inspect the complete error:</p>
<pre><code class="language-js">console.log(error);
</code></pre>
<p>This is especially useful during debugging because the error often contains a <strong>stack trace</strong> showing where the problem originated.</p>
<p>A common pattern is:</p>
<pre><code class="language-js">try {
  riskyOperation();
} catch (error) {
  console.error("Operation failed:", error);
}
</code></pre>
<p>During development, don't hide useful error information unnecessarily.</p>
<hr />
<h2>What Does <code>finally</code> Do?</h2>
<p>Sometimes you need certain code to run <strong>whether an operation succeeds or fails</strong>.</p>
<p>That's what <code>finally</code> is for.</p>
<pre><code class="language-js">try {
  // Code
} catch (error) {
  // Handle error
} finally {
  // Always runs
}
</code></pre>
<p>For example:</p>
<pre><code class="language-js">try {
  console.log("Processing...");
} catch (error) {
  console.log("Something went wrong");
} finally {
  console.log("Finished");
}
</code></pre>
<p>The <code>finally</code> block runs after the <code>try</code> or <code>catch</code> block.</p>
<p>The execution order is:</p>
<pre><code class="language-text">          try
           │
      ┌────┴────┐
      ↓         ↓
   Success    Error
      │         │
      │       catch
      │         │
      └────┬────┘
           ↓
        finally
</code></pre>
<h2>When Is <code>finally</code> Useful?</h2>
<p>It's commonly used for cleanup.</p>
<p>For example, imagine showing a loading indicator while an API request is running:</p>
<pre><code class="language-js">showLoading();

try {
  await fetchData();
} catch (error) {
  console.error(error);
} finally {
  hideLoading();
}
</code></pre>
<p>Whether the request succeeds or fails, the loading indicator should disappear.</p>
<p>That's a perfect use case for <code>finally</code>.</p>
<hr />
<h2>Throwing Your Own Errors</h2>
<p>JavaScript doesn't only throw errors automatically.</p>
<p>You can deliberately throw an error using <code>throw</code>.</p>
<pre><code class="language-js">throw new Error("Something went wrong");
</code></pre>
<p>For example:</p>
<pre><code class="language-js">function withdraw(balance, amount) {
  if (amount &gt; balance) {
    throw new Error("Insufficient balance");
  }

  return balance - amount;
}
</code></pre>
<p>Now the function explicitly rejects an invalid operation.</p>
<p>You can handle that error elsewhere:</p>
<pre><code class="language-js">try {
  const remaining = withdraw(100, 150);
  console.log(remaining);
} catch (error) {
  console.log(error.message);
}
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Insufficient balance
</code></pre>
<p>This is useful because the function can communicate:</p>
<blockquote>
<p>"The input or operation isn't valid, so I can't continue normally."</p>
</blockquote>
<hr />
<h2>Why Use <code>new Error()</code>?</h2>
<p>You could technically throw other values:</p>
<pre><code class="language-js">throw "Something went wrong";
</code></pre>
<p>But it's generally better to throw an <code>Error</code> object:</p>
<pre><code class="language-js">throw new Error("Something went wrong");
</code></pre>
<p>Error objects provide useful information such as:</p>
<ul>
<li><p><code>name</code></p>
</li>
<li><p><code>message</code></p>
</li>
<li><p>stack information</p>
</li>
</ul>
<p>This makes errors more consistent and useful for debugging.</p>
<hr />
<h2>Custom Error Types</h2>
<p>For larger applications, you may want errors that represent specific situations.</p>
<p>JavaScript allows you to create custom error classes:</p>
<pre><code class="language-js">class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}
</code></pre>
<p>You can then throw one:</p>
<pre><code class="language-js">throw new ValidationError("Email is required");
</code></pre>
<p>And handle it:</p>
<pre><code class="language-js">try {
  throw new ValidationError("Email is required");
} catch (error) {
  console.log(error.name);
  console.log(error.message);
}
</code></pre>
<p>This becomes useful when different errors need different handling.</p>
<p>For example:</p>
<pre><code class="language-text">ValidationError
    ↓
Show validation message

NetworkError
    ↓
Retry request

AuthenticationError
    ↓
Ask user to log in
</code></pre>
<p>You don't need custom error classes for every project, but they're valuable when an application has more complex error-handling requirements.</p>
<hr />
<h2>Error Handling With Functions</h2>
<p>Error handling becomes especially useful when a function performs an operation that can fail.</p>
<p>For example:</p>
<pre><code class="language-js">function parseUserData(data) {
  try {
    return JSON.parse(data);
  } catch (error) {
    console.error("Invalid JSON:", error.message);
    return null;
  }
}
</code></pre>
<p>Now invalid input doesn't unexpectedly break the caller.</p>
<pre><code class="language-js">const user = parseUserData("invalid data");

if (user === null) {
  console.log("Could not load user data");
}
</code></pre>
<p>This is an example of <strong>graceful failure</strong>.</p>
<p>Instead of pretending the operation cannot fail, the program recognizes the failure and decides how to respond.</p>
<hr />
<h2>Error Handling With Promises and <code>async/await</code></h2>
<p>Error handling is particularly important with asynchronous code.</p>
<p>With Promise chains, <code>.catch()</code> handles rejected Promises:</p>
<pre><code class="language-js">fetch("/api/users")
  .then((response) =&gt; response.json())
  .then((users) =&gt; {
    console.log(users);
  })
  .catch((error) =&gt; {
    console.error("Request failed:", error);
  });
</code></pre>
<p>With <code>async/await</code>, you can use <code>try/catch</code>:</p>
<pre><code class="language-js">async function loadUsers() {
  try {
    const response = await fetch("/api/users");
    const users = await response.json();

    console.log(users);
  } catch (error) {
    console.error("Request failed:", error);
  }
}
</code></pre>
<p>This makes the relationship clear:</p>
<pre><code class="language-text">Promise rejection
      ↓
.catch()

async/await
      ↓
try/catch
</code></pre>
<p>And <code>finally</code> works here too:</p>
<pre><code class="language-js">async function loadUsers() {
  showLoading();

  try {
    const response = await fetch("/api/users");
    const users = await response.json();

    console.log(users);
  } catch (error) {
    console.error(error);
  } finally {
    hideLoading();
  }
}
</code></pre>
<p>This is a very common pattern in modern JavaScript applications.</p>
<hr />
<h2>Error Handling Is Not Just About Avoiding Crashes</h2>
<p>Good error handling has two audiences:</p>
<h3>For users</h3>
<p>Give them a useful response.</p>
<p>Instead of:</p>
<pre><code class="language-text">TypeError: Cannot read properties of undefined
</code></pre>
<p>A user might see:</p>
<pre><code class="language-text">We couldn't load your profile. Please try again.
</code></pre>
<h3>For developers</h3>
<p>Keep enough information to understand and fix the problem.</p>
<p>For example:</p>
<pre><code class="language-js">catch (error) {
  console.error("Profile request failed:", error);
}
</code></pre>
<p>The goal is therefore:</p>
<pre><code class="language-text">Technical error
      ↓
Capture it
      ↓
Understand it
      ↓
Handle it appropriately
      ↓
Give the user a useful result
</code></pre>
<hr />
<h2>Don't Hide Every Error</h2>
<p>Error handling doesn't mean putting everything inside <code>try/catch</code> and ignoring failures.</p>
<p>Avoid code like:</p>
<pre><code class="language-js">try {
  doSomething();
} catch (error) {
  // Ignore everything
}
</code></pre>
<p>This can make debugging much harder.</p>
<p>If an error matters, handle it meaningfully.</p>
<p>For example:</p>
<pre><code class="language-js">try {
  saveProfile();
} catch (error) {
  console.error("Could not save profile:", error);
  showErrorMessage();
}
</code></pre>
<p>Now both the application and developer get useful information.</p>
<hr />
<h2><code>try → catch → finally</code>: The Core Model</h2>
<p>You can remember the entire system with three questions:</p>
<h3><code>try</code></h3>
<p><strong>What code might fail?</strong></p>
<pre><code class="language-js">try {
  riskyOperation();
}
</code></pre>
<h3><code>catch</code></h3>
<p><strong>What should happen if it fails?</strong></p>
<pre><code class="language-js">catch (error) {
  handleError(error);
}
</code></pre>
<h3><code>finally</code></h3>
<p><strong>What must happen regardless?</strong></p>
<pre><code class="language-js">finally {
  cleanup();
}
</code></pre>
<p>Together:</p>
<pre><code class="language-plaintext">             try
              │
       ┌──────┴──────┐
       ↓             ↓
    Success        Error
       │             │
       │           catch
       │             │
       └──────┬──────┘
              ↓
           finally
              ↓
           Continue
</code></pre>
<hr />
<h2>Best Practices</h2>
<p>A few simple rules will take you a long way:</p>
<h3>1. Handle errors where you can actually respond to them</h3>
<p>Don't catch an error just to immediately ignore it.</p>
<h3>2. Preserve useful error information</h3>
<p>During development, inspect the error and stack trace.</p>
<h3>3. Use <code>throw new Error()</code></h3>
<p>Prefer standard <code>Error</code> objects over throwing strings or arbitrary values.</p>
<h3>4. Use <code>finally</code> for cleanup</h3>
<p>Loading states, temporary resources, and other cleanup operations are good candidates.</p>
<h3>5. Give users useful feedback</h3>
<p>Technical error messages are useful to developers, not usually to users.</p>
<h3>6. Don't use errors for normal control flow</h3>
<p>If something is an expected condition, ordinary logic is often clearer than throwing and catching an error.</p>
<hr />
<h2>Quick Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Purpose</th>
</tr>
</thead>
<tbody><tr>
<td><code>try</code></td>
<td>Run code that might fail</td>
</tr>
<tr>
<td><code>catch</code></td>
<td>Handle an error</td>
</tr>
<tr>
<td><code>finally</code></td>
<td>Run cleanup regardless of outcome</td>
</tr>
<tr>
<td><code>throw</code></td>
<td>Create/trigger an error</td>
</tr>
<tr>
<td><code>new Error()</code></td>
<td>Create a standard Error object</td>
</tr>
<tr>
<td><code>.catch()</code></td>
<td>Handle rejected Promises</td>
</tr>
<tr>
<td><code>async/await</code> + <code>try/catch</code></td>
<td>Handle asynchronous errors</td>
</tr>
</tbody></table>
<hr />
<h2>Final Takeaway</h2>
<p>Errors are not necessarily signs that your application is badly written.</p>
<p><strong>Unexpected failures are part of real software.</strong></p>
<p>Good JavaScript code anticipates that operations can fail and handles those failures deliberately.</p>
<p>The core mental model is simple:</p>
<pre><code class="language-text">        try
         ↓
Run risky operation
         ↓
 ┌───────────────┐
 │               │
Success         Error
 │               │
 │            catch
 │               │
 └───────┬───────┘
         ↓
      finally
         ↓
      Continue
</code></pre>
<p>Use <code>try</code> to identify code that might fail, <code>catch</code> to respond to the failure, <code>finally</code> for cleanup, and <code>throw</code> when your own code needs to report an invalid operation.</p>
<p>The goal of error handling isn't to pretend errors don't happen.</p>
<p>It's to make sure that <strong>when they do happen, your application fails gracefully, your users get a useful experience, and you still have enough information to debug the problem.</strong></p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Promises Explained: From Callbacks to Async/Await]]></title><description><![CDATA[JavaScript often needs to wait for things that don't finish immediately.
Fetching data from an API, waiting for a timer, reading a file, or saving information somewhere can all take time.
But JavaScri]]></description><link>https://maazzz.hashnode.dev/javascript-promises-explained-from-callbacks-to-async-await</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-promises-explained-from-callbacks-to-async-await</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Wed, 02 Sep 2026 20:16:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/4ed29705-2a47-4afe-ab4c-9c0f619c7a20.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript often needs to wait for things that don't finish immediately.</p>
<p>Fetching data from an API, waiting for a timer, reading a file, or saving information somewhere can all take time.</p>
<p>But JavaScript shouldn't stop doing everything else while waiting.</p>
<p>So how do we handle a value that <strong>isn't available yet</strong>?</p>
<p>JavaScript has evolved several ways to handle asynchronous operations:</p>
<pre><code class="language-text">Callbacks
    ↓
Promises
    ↓
async/await
</code></pre>
<p>In this article, we'll understand that evolution and, most importantly, learn <strong>how Promises work, why they matter, and when to use them</strong>.</p>
<hr />
<h2>The Problem: Some Results Take Time</h2>
<p>Consider an API request:</p>
<pre><code class="language-js">const response = fetch("/api/users");
</code></pre>
<p>The response doesn't arrive instantly.</p>
<p>The application has to:</p>
<ol>
<li><p>Start the request</p>
</li>
<li><p>Wait for the server</p>
</li>
<li><p>Receive the response</p>
</li>
<li><p>Process the result</p>
</li>
</ol>
<p>The important part is that we don't want JavaScript to freeze while waiting.</p>
<p>Instead, we need a way to say:</p>
<blockquote>
<p>"Start this operation. When the result is ready, do something with it."</p>
</blockquote>
<p>That's the problem asynchronous programming needs to solve.</p>
<hr />
<h2>1. Callbacks: The Original Approach</h2>
<p>One of the earliest common solutions was the <strong>callback</strong>.</p>
<p>A callback is simply a function that you give to another function so it can call it later.</p>
<pre><code class="language-js">getUser((user) =&gt; {
  console.log(user);
});
</code></pre>
<p>The idea is straightforward:</p>
<pre><code class="language-text">Start operation
      ↓
Wait
      ↓
Result available
      ↓
Run callback
</code></pre>
<p>Callbacks work well for simple operations.</p>
<p>The problem appears when multiple asynchronous operations depend on each other.</p>
<p>For example:</p>
<pre><code class="language-js">getUser((user) =&gt; {
  getOrders(user.id, (orders) =&gt; {
    getOrderDetails(orders[0], (order) =&gt; {
      console.log(order);
    });
  });
});
</code></pre>
<p>Now the code becomes deeply nested.</p>
<p>As more operations are added, the flow becomes harder to read and maintain.</p>
<p>This is commonly called <strong>callback hell</strong>.</p>
<p>The problem isn't that callbacks are bad.</p>
<p>The problem is that deeply nested callbacks make complex asynchronous flows difficult to manage.</p>
<p>And this is where Promises become useful.</p>
<hr />
<h2>2. Promises: A Better Way to Represent Future Results</h2>
<p>A <strong>Promise represents the eventual result of an asynchronous operation</strong>.</p>
<p>Think of it as a placeholder for a value you don't have yet.</p>
<p>For example:</p>
<pre><code class="language-js">const promise = fetch("/api/users");
</code></pre>
<p>You don't have the server's response immediately.</p>
<p>But you have a Promise representing the response that will eventually arrive.</p>
<p>Think of it like this:</p>
<pre><code class="language-text">              Promise
                 │
          "I don't have
           the result yet"
                 │
          ┌──────┴──────┐
          ↓             ↓
       Success        Failure
          ↓             ↓
       Result          Error
</code></pre>
<p>This is the core idea behind Promises.</p>
<hr />
<h2>3. The Three States of a Promise</h2>
<p>Every Promise has one of three states.</p>
<h3>Pending</h3>
<p>The operation is still in progress.</p>
<pre><code class="language-text">"Waiting..."
</code></pre>
<h3>Fulfilled</h3>
<p>The operation completed successfully.</p>
<pre><code class="language-text">"Here's your result."
</code></pre>
<h3>Rejected</h3>
<p>The operation failed.</p>
<pre><code class="language-text">"Something went wrong."
</code></pre>
<p>The lifecycle looks like this:</p>
<pre><code class="language-text">             PENDING
                │
          ┌─────┴─────┐
          ↓           ↓
     FULFILLED     REJECTED
          │           │
          ↓           ↓
       Success       Error
</code></pre>
<p>A Promise starts as <strong>pending</strong> and eventually becomes either <strong>fulfilled</strong> or <strong>rejected</strong>.</p>
<p>Once it settles, its state doesn't change again.</p>
<hr />
<h2>4. Creating a Promise</h2>
<p>You can create a Promise using the <code>Promise</code> constructor:</p>
<pre><code class="language-js">const promise = new Promise((resolve, reject) =&gt; {
  // operation
});
</code></pre>
<p>It provides two functions:</p>
<ul>
<li><p><code>resolve()</code> → marks the Promise as fulfilled</p>
</li>
<li><p><code>reject()</code> → marks the Promise as rejected</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-js">const promise = new Promise((resolve, reject) =&gt; {
  resolve("Operation completed");
});
</code></pre>
<p>The Promise is now fulfilled with <code>"Operation completed"</code>.</p>
<p>Or:</p>
<pre><code class="language-js">const promise = new Promise((resolve, reject) =&gt; {
  reject("Operation failed");
});
</code></pre>
<p>Now the Promise is rejected.</p>
<p>In real applications, you will often <strong>consume</strong> Promises returned by APIs and libraries rather than create them yourself.</p>
<p>For example:</p>
<pre><code class="language-js">fetch("/api/users");
</code></pre>
<p><code>fetch()</code> returns a Promise.</p>
<hr />
<h2>5. Handling a Successful Promise</h2>
<p>To handle a fulfilled Promise, use <code>.then()</code>.</p>
<pre><code class="language-js">promise.then((result) =&gt; {
  console.log(result);
});
</code></pre>
<p>For example:</p>
<pre><code class="language-js">const promise = new Promise((resolve) =&gt; {
  setTimeout(() =&gt; {
    resolve("Data received");
  }, 2000);
});

promise.then((result) =&gt; {
  console.log(result);
});
</code></pre>
<p>After the operation completes:</p>
<pre><code class="language-text">Data received
</code></pre>
<p>The basic idea is:</p>
<pre><code class="language-text">Promise
   ↓
.then()
   ↓
Handle successful result
</code></pre>
<hr />
<h2>6. Handling Promise Errors</h2>
<p>What happens when the operation fails?</p>
<p>Use <code>.catch()</code>.</p>
<pre><code class="language-js">const promise = new Promise((resolve, reject) =&gt; {
  reject("Request failed");
});

promise
  .then((result) =&gt; {
    console.log(result);
  })
  .catch((error) =&gt; {
    console.log(error);
  });
</code></pre>
<p>Now the rejected Promise is handled by <code>.catch()</code>.</p>
<p>Think of it as:</p>
<pre><code class="language-text">.then()  → successful result
.catch() → error
</code></pre>
<p>You can also use <code>.finally()</code> when something should happen regardless of success or failure:</p>
<pre><code class="language-js">promise
  .then((result) =&gt; {
    console.log(result);
  })
  .catch((error) =&gt; {
    console.log(error);
  })
  .finally(() =&gt; {
    console.log("Finished");
  });
</code></pre>
<p>For example, you might use <code>finally()</code> to hide a loading indicator after an API request finishes.</p>
<hr />
<h2>7. Promise Chaining</h2>
<p>One of the most useful features of Promises is <strong>chaining</strong>.</p>
<p>Suppose we need to:</p>
<pre><code class="language-text">Get user
   ↓
Get their orders
   ↓
Get order details
   ↓
Display result
</code></pre>
<p>With Promises:</p>
<pre><code class="language-js">getUser()
  .then((user) =&gt; {
    return getOrders(user.id);
  })
  .then((orders) =&gt; {
    return getOrderDetails(orders[0]);
  })
  .then((order) =&gt; {
    console.log(order);
  })
  .catch((error) =&gt; {
    console.log(error);
  });
</code></pre>
<p>This is easier to follow because the asynchronous flow moves mostly from <strong>top to bottom</strong> instead of becoming deeply nested.</p>
<h3>How does the chain work?</h3>
<p>A <code>.then()</code> returns a Promise.</p>
<p>If you return another Promise from it:</p>
<pre><code class="language-js">.then((user) =&gt; {
  return getOrders(user.id);
})
</code></pre>
<p>the next <code>.then()</code> waits for that returned Promise.</p>
<p>So:</p>
<pre><code class="language-text">Promise 1
   ↓
.then()
   ↓
Promise 2
   ↓
.then()
   ↓
Promise 3
   ↓
.then()
   ↓
Result
</code></pre>
<p>This is the heart of Promise chaining.</p>
<hr />
<h2>8. Why Returning Matters</h2>
<p>Consider:</p>
<pre><code class="language-js">getUser()
  .then((user) =&gt; {
    return getOrders(user.id);
  })
  .then((orders) =&gt; {
    console.log(orders);
  });
</code></pre>
<p>The <code>return</code> passes the Promise from <code>getOrders()</code> to the next step.</p>
<p>Without it:</p>
<pre><code class="language-js">getUser()
  .then((user) =&gt; {
    getOrders(user.id);
  })
  .then((orders) =&gt; {
    console.log(orders);
  });
</code></pre>
<p>the next <code>.then()</code> doesn't wait for <code>getOrders()</code> in the same way.</p>
<p>So when building chains, remember:</p>
<blockquote>
<p><strong>Return the Promise you want the next</strong> <code>.then()</code> <strong>to wait for.</strong></p>
</blockquote>
<hr />
<h2>9. Callbacks vs Promises</h2>
<p>Here's the difference at a high level.</p>
<h3>Callback style</h3>
<pre><code class="language-js">getUser((user) =&gt; {
  getOrders(user.id, (orders) =&gt; {
    getOrderDetails(orders[0], (order) =&gt; {
      console.log(order);
    });
  });
});
</code></pre>
<h3>Promise style</h3>
<pre><code class="language-js">getUser()
  .then((user) =&gt; getOrders(user.id))
  .then((orders) =&gt; getOrderDetails(orders[0]))
  .then((order) =&gt; console.log(order))
  .catch((error) =&gt; console.log(error));
</code></pre>
<p>The Promise version gives the flow a more predictable structure:</p>
<pre><code class="language-text">Operation
   ↓
Operation
   ↓
Operation
   ↓
Success

Any failure
   ↓
.catch()
</code></pre>
<p>Promises don't eliminate asynchronous complexity.</p>
<p>They provide a <strong>better structure for managing it</strong>.</p>
<hr />
<h2>10. Where Promises Are Used</h2>
<p>Promises are everywhere in modern JavaScript.</p>
<h3>API requests</h3>
<pre><code class="language-js">fetch("/api/products")
  .then((response) =&gt; response.json())
  .then((products) =&gt; {
    console.log(products);
  })
  .catch((error) =&gt; {
    console.log(error);
  });
</code></pre>
<h3>Timers</h3>
<p>You can wrap timer-based operations in Promises:</p>
<pre><code class="language-js">const wait = (ms) =&gt;
  new Promise((resolve) =&gt; {
    setTimeout(resolve, ms);
  });

wait(2000).then(() =&gt; {
  console.log("Two seconds passed");
});
</code></pre>
<h3>File operations</h3>
<p>Node.js APIs provide Promise-based versions of many file operations:</p>
<pre><code class="language-js">import { readFile } from "node:fs/promises";

readFile("data.txt", "utf8")
  .then((data) =&gt; {
    console.log(data);
  })
  .catch((error) =&gt; {
    console.log(error);
  });
</code></pre>
<p>The common pattern is:</p>
<pre><code class="language-text">Start asynchronous operation
          ↓
       Promise
          ↓
   ┌──────┴──────┐
   ↓             ↓
Success        Failure
   ↓             ↓
 .then()       .catch()
</code></pre>
<hr />
<h2>11. Then Came async/await</h2>
<p>Promises solved a lot of readability problems.</p>
<p>But long chains can still become difficult to read.</p>
<p>That's where <code>async/await</code> comes in.</p>
<p><code>async/await</code> is essentially a cleaner way to work with Promises.</p>
<p>Consider:</p>
<pre><code class="language-js">getUser()
  .then((user) =&gt; getOrders(user.id))
  .then((orders) =&gt; getOrderDetails(orders[0]))
  .then((order) =&gt; {
    console.log(order);
  })
  .catch((error) =&gt; {
    console.log(error);
  });
</code></pre>
<p>With <code>async/await</code>:</p>
<pre><code class="language-js">async function loadOrder() {
  try {
    const user = await getUser();
    const orders = await getOrders(user.id);
    const order = await getOrderDetails(orders[0]);

    console.log(order);
  } catch (error) {
    console.log(error);
  }
}
</code></pre>
<p>The second version reads more like normal step-by-step code:</p>
<pre><code class="language-text">Get user
   ↓
Get orders
   ↓
Get order details
   ↓
Display order
</code></pre>
<p>That's the major benefit of <code>async/await</code>.</p>
<hr />
<h2>12. How async/await Actually Relates to Promises</h2>
<p>This distinction is important:</p>
<p><code>async/await</code> <strong>does not replace Promises.</strong></p>
<p>It works <strong>with</strong> Promises.</p>
<p>An <code>async</code> function always returns a Promise:</p>
<pre><code class="language-js">async function getMessage() {
  return "Hello";
}
</code></pre>
<p>So:</p>
<pre><code class="language-js">getMessage().then((message) =&gt; {
  console.log(message);
});
</code></pre>
<p>works because <code>getMessage()</code> returns a Promise.</p>
<p>And <code>await</code> is used to wait for a Promise to settle:</p>
<pre><code class="language-js">const message = await getMessage();
</code></pre>
<p>You can think of it like this:</p>
<pre><code class="language-text">Callbacks
    ↓
A way to handle results later

Promises
    ↓
Represent and manage future results

async/await
    ↓
Cleaner syntax for working with Promises
</code></pre>
<p>So learning Promises is important even if you mostly write <code>async/await</code>.</p>
<hr />
<h2>13. When Should You Use Each?</h2>
<h3>Callbacks</h3>
<p>Callbacks are still useful when:</p>
<ul>
<li><p>Working with callback-based APIs</p>
</li>
<li><p>Handling event listeners</p>
</li>
<li><p>Passing a function to execute later</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-js">button.addEventListener("click", () =&gt; {
  console.log("Clicked");
});
</code></pre>
<p>Not every callback is an asynchronous workflow that needs Promises.</p>
<hr />
<h3>Promises</h3>
<p>Use Promises when:</p>
<ul>
<li><p>An operation produces a future result</p>
</li>
<li><p>You need to compose asynchronous operations</p>
</li>
<li><p>You're working with Promise-based APIs</p>
</li>
<li><p>You want <code>.then()</code>, <code>.catch()</code>, or Promise utilities</p>
</li>
</ul>
<p>Promises are especially important for understanding how asynchronous JavaScript actually works.</p>
<hr />
<h3>async/await</h3>
<p>Use <code>async/await</code> when:</p>
<ul>
<li><p>You want Promise-based code to read sequentially</p>
</li>
<li><p>You have multiple dependent asynchronous operations</p>
</li>
<li><p>You want straightforward <code>try/catch</code> error handling</p>
</li>
<li><p>A Promise chain is becoming difficult to read</p>
</li>
</ul>
<p>In modern JavaScript applications, <code>async/await</code> is often the most readable way to consume Promises.</p>
<hr />
<h2>14. A Simple Model</h2>
<p>Don't think of a Promise as "a delayed value."</p>
<p>Think of it as:</p>
<blockquote>
<p><strong>A container representing the future outcome of an operation.</strong></p>
</blockquote>
<p>That outcome can be:</p>
<pre><code class="language-text">             Promise
                │
             Pending
                │
        ┌───────┴───────┐
        ↓               ↓
    Fulfilled        Rejected
        │               │
        ↓               ↓
    .then()          .catch()
</code></pre>
<p>And when you want to write that Promise-based flow in a more sequential style:</p>
<pre><code class="language-js">async function run() {
  try {
    const result = await somePromise();
    console.log(result);
  } catch (error) {
    console.log(error);
  }
}
</code></pre>
<hr />
<h2>Promise Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Concept</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td>Promise</td>
<td>Represents an eventual result</td>
</tr>
<tr>
<td>Pending</td>
<td>Operation hasn't finished</td>
</tr>
<tr>
<td>Fulfilled</td>
<td>Operation succeeded</td>
</tr>
<tr>
<td>Rejected</td>
<td>Operation failed</td>
</tr>
<tr>
<td><code>resolve()</code></td>
<td>Fulfill a Promise</td>
</tr>
<tr>
<td><code>reject()</code></td>
<td>Reject a Promise</td>
</tr>
<tr>
<td><code>.then()</code></td>
<td>Handle success</td>
</tr>
<tr>
<td><code>.catch()</code></td>
<td>Handle errors</td>
</tr>
<tr>
<td><code>.finally()</code></td>
<td>Run after settlement</td>
</tr>
<tr>
<td>Chaining</td>
<td>Connect multiple Promise operations</td>
</tr>
<tr>
<td><code>async</code></td>
<td>Makes a function return a Promise</td>
</tr>
<tr>
<td><code>await</code></td>
<td>Waits for a Promise inside an async function</td>
</tr>
</tbody></table>
<hr />
<h2>Final Takeaway</h2>
<p>JavaScript's approach to asynchronous code has evolved:</p>
<pre><code class="language-text">Callbacks
   ↓
Promises
   ↓
async/await
</code></pre>
<p>Callbacks provided a way to run code when an operation finished, but deeply nested callbacks could become difficult to manage.</p>
<p>Promises introduced a structured representation of a <strong>future result</strong>, with clear states and methods for handling success and failure.</p>
<p>Then <code>async/await</code> provided a cleaner syntax for consuming those Promises.</p>
<p>The most important thing to remember is:</p>
<blockquote>
<p><strong>Promises are the foundation.</strong> <code>async/await</code> <strong>is a cleaner way to work with them.</strong></p>
</blockquote>
<p>Once you understand that a Promise starts <strong>pending</strong>, becomes <strong>fulfilled or rejected</strong>, and can be handled with <code>.then()</code> and <code>.catch()</code>, asynchronous JavaScript becomes much easier to reason about.</p>
<p>And when several asynchronous operations need to happen in sequence, Promise chaining and <code>async/await</code> give you readable ways to express that flow.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Objects in JavaScript: Properties, Values, and How to Work With Objects]]></title><description><![CDATA[If you've written JavaScript, you've already worked with objects.
Users, products, students, orders, API responses, application settings, and even parts of your UI state are commonly represented as ob]]></description><link>https://maazzz.hashnode.dev/understanding-objects-in-javascript-properties-values-and-how-to-work-with-objects</link><guid isPermaLink="true">https://maazzz.hashnode.dev/understanding-objects-in-javascript-properties-values-and-how-to-work-with-objects</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Tue, 01 Sep 2026 19:12:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/56cdf539-d383-49ed-9fe9-bcb4a26b0936.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've written JavaScript, you've already worked with <strong>objects</strong>.</p>
<p>Users, products, students, orders, API responses, application settings, and even parts of your UI state are commonly represented as objects.</p>
<p>But what exactly is an object, and how do you work with one?</p>
<p>In this guide, you'll learn the fundamentals of JavaScript objects step by step — from creating and accessing properties to updating, deleting, and looping through them.</p>
<hr />
<h2>What Is an Object in JavaScript?</h2>
<p>A JavaScript <strong>object</strong> is a collection of <strong>key-value pairs</strong>.</p>
<p>Think of it as a way to group related information under meaningful names.</p>
<p>For example, instead of storing a person's information separately:</p>
<pre><code class="language-js">const name = "Maaz";
const age = 20;
const city = "Multan";
</code></pre>
<p>You can group everything into one object:</p>
<pre><code class="language-js">const person = {
  name: "Maaz",
  age: 20,
  city: "Multan"
};
</code></pre>
<p>Now <code>person</code> represents one entity, and its properties describe that entity.</p>
<p>You can visualize it like this:</p>
<pre><code class="language-text">person
 ├── name → "Maaz"
 ├── age  → 20
 └── city → "Multan"
</code></pre>
<p>The names on the left are <strong>keys</strong> (or property names), and the data on the right are their <strong>values</strong>.</p>
<h3>Why Do We Need Objects?</h3>
<p>Objects are useful when multiple pieces of data belong together.</p>
<p>For example:</p>
<pre><code class="language-js">const product = {
  name: "Laptop",
  price: 1200,
  inStock: true
};
</code></pre>
<p>Instead of managing <code>name</code>, <code>price</code>, and <code>inStock</code> separately, the object keeps everything related to the product together.</p>
<p>This becomes especially useful when working with larger applications and structured data.</p>
<hr />
<h2>Creating Objects</h2>
<p>The most common way to create an object is with an <strong>object literal</strong>.</p>
<pre><code class="language-js">const student = {
  name: "Ali",
  age: 21,
  course: "Computer Science"
};
</code></pre>
<p>You can also create an empty object and add properties later:</p>
<pre><code class="language-js">const student = {};

student.name = "Ali";
student.age = 21;
student.course = "Computer Science";
</code></pre>
<p>Both approaches create an object.</p>
<p>The first approach is usually cleaner when you already know the properties you need.</p>
<hr />
<h2>Accessing Object Properties</h2>
<p>Once you have an object, you need to access its values.</p>
<p>JavaScript provides two common ways:</p>
<ol>
<li><p>Dot notation</p>
</li>
<li><p>Bracket notation</p>
</li>
</ol>
<h2>1. Dot Notation</h2>
<p>Use a dot followed by the property name:</p>
<pre><code class="language-js">const person = {
  name: "Maaz",
  age: 20
};

console.log(person.name);
console.log(person.age);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Maaz
20
</code></pre>
<p>Dot notation is usually the simplest and most readable option.</p>
<hr />
<h2>2. Bracket Notation</h2>
<p>You can also access a property using square brackets:</p>
<pre><code class="language-js">console.log(person["name"]);
console.log(person["age"]);
</code></pre>
<p>This produces the same result.</p>
<p>Bracket notation becomes especially useful when the property name is stored in a variable.</p>
<pre><code class="language-js">const property = "name";

console.log(person[property]);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Maaz
</code></pre>
<p>This is different from:</p>
<pre><code class="language-js">console.log(person.property);
</code></pre>
<p>Here, JavaScript looks for a property literally named <code>"property"</code>.</p>
<h3>Simple Rule</h3>
<pre><code class="language-text">Known property name
→ person.name

Property name stored in a variable
→ person[property]
</code></pre>
<hr />
<h2>Updating Object Properties</h2>
<p>Object properties can be changed after the object is created.</p>
<p>For example:</p>
<pre><code class="language-js">const student = {
  name: "Ali",
  age: 21
};

student.age = 22;

console.log(student.age);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">22
</code></pre>
<p>The <code>age</code> property originally contained <code>21</code>, but we replaced it with <code>22</code>.</p>
<p>Objects are therefore useful for representing data that can change while a program is running.</p>
<hr />
<h2>Adding New Properties</h2>
<p>You don't need to define every property when creating the object.</p>
<p>You can add new properties later:</p>
<pre><code class="language-js">const student = {
  name: "Ali"
};

student.age = 21;
student.course = "Computer Science";
</code></pre>
<p>Now the object contains:</p>
<pre><code class="language-js">{
  name: "Ali",
  age: 21,
  course: "Computer Science"
}
</code></pre>
<p>You can also use bracket notation when the property name is dynamic:</p>
<pre><code class="language-js">const key = "email";

student[key] = "ali@example.com";
</code></pre>
<hr />
<h2>Deleting Properties</h2>
<p>If you no longer need a property, you can remove it using the <code>delete</code> operator.</p>
<pre><code class="language-js">const student = {
  name: "Ali",
  age: 21,
  course: "Computer Science"
};

delete student.age;
</code></pre>
<p>The object is now:</p>
<pre><code class="language-js">{
  name: "Ali",
  course: "Computer Science"
}
</code></pre>
<p>So the basic operations are:</p>
<pre><code class="language-text">Create → const object = {}
Read   → object.key
Update → object.key = value
Add    → object.newKey = value
Delete → delete object.key
</code></pre>
<hr />
<h2>Object vs Array</h2>
<p>A common beginner question is:</p>
<p><strong>When should I use an object, and when should I use an array?</strong></p>
<p>The easiest way to think about it is:</p>
<blockquote>
<p><strong>Objects describe entities. Arrays store ordered collections.</strong></p>
</blockquote>
<p>For example, an object can represent one person:</p>
<pre><code class="language-js">const person = {
  name: "Ali",
  age: 21,
  city: "Lahore"
};
</code></pre>
<p>An array can store multiple cities:</p>
<pre><code class="language-js">const cities = [
  "Lahore",
  "Karachi",
  "Islamabad"
];
</code></pre>
<p>You can also combine both:</p>
<pre><code class="language-js">const students = [
  {
    name: "Ali",
    age: 21
  },
  {
    name: "Sara",
    age: 22
  }
];
</code></pre>
<p>Here:</p>
<ul>
<li><p>The <strong>array</strong> represents a collection of students.</p>
</li>
<li><p>Each <strong>object</strong> represents one student.</p>
</li>
</ul>
<p>This combination is extremely common when working with real-world application data and API responses.</p>
<hr />
<h2>Looping Through Object Properties</h2>
<p>Sometimes you don't know the property names beforehand, or you simply want to process every property.</p>
<p>JavaScript provides <code>Object.keys()</code> for this.</p>
<pre><code class="language-js">const student = {
  name: "Ali",
  age: 21,
  course: "Computer Science"
};

console.log(Object.keys(student));
</code></pre>
<p>Output:</p>
<pre><code class="language-text">["name", "age", "course"]
</code></pre>
<p><code>Object.keys()</code> returns an <strong>array containing the object's own enumerable property names</strong>.</p>
<p>You can then loop through those keys:</p>
<pre><code class="language-js">for (const key of Object.keys(student)) {
  console.log(key);
}
</code></pre>
<p>Output:</p>
<pre><code class="language-text">name
age
course
</code></pre>
<p>But what if you also want each value?</p>
<p>Use the key to access the corresponding property:</p>
<pre><code class="language-js">for (const key of Object.keys(student)) {
  console.log(key, student[key]);
}
</code></pre>
<p>Output:</p>
<pre><code class="language-text">name Ali
age 21
course Computer Science
</code></pre>
<p>Notice why bracket notation is useful here:</p>
<pre><code class="language-js">student[key]
</code></pre>
<p>Because <code>key</code> is a variable containing the property name.</p>
<hr />
<h2>A Complete Example</h2>
<p>Let's put everything together.</p>
<p>Suppose we want to create a student object, update a property, add another property, and then print all its properties.</p>
<pre><code class="language-js">const student = {
  name: "Ali",
  age: 21,
  course: "Computer Science"
};

// Update a property
student.age = 22;

// Add a property
student.city = "Lahore";

// Print all keys and values
for (const key of Object.keys(student)) {
  console.log(`${key}: ${student[key]}`);
}
</code></pre>
<p>Output:</p>
<pre><code class="language-text">name: Ali
age: 22
course: Computer Science
city: Lahore
</code></pre>
<p>This small example demonstrates several fundamental object operations:</p>
<pre><code class="language-text">Create
  ↓
Access
  ↓
Update
  ↓
Add
  ↓
Loop
</code></pre>
<hr />
<h2>A Simple Mental Model for Objects</h2>
<p>When you're unsure whether an object is the right structure, ask:</p>
<blockquote>
<p><strong>What entity am I describing, and what properties does it have?</strong></p>
</blockquote>
<p>For a product:</p>
<pre><code class="language-js">const product = {
  name: "Keyboard",
  price: 80,
  inStock: true
};
</code></pre>
<p>For a user:</p>
<pre><code class="language-js">const user = {
  username: "developer123",
  email: "user@example.com",
  isVerified: true
};
</code></pre>
<p>For an order:</p>
<pre><code class="language-js">const order = {
  id: 1001,
  total: 250,
  status: "shipped"
};
</code></pre>
<p>The pattern stays the same:</p>
<p><strong>Entity → Properties → Values</strong></p>
<hr />
<h2>JavaScript Objects Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Syntax</th>
</tr>
</thead>
<tbody><tr>
<td>Create</td>
<td><code>const obj = {}</code></td>
</tr>
<tr>
<td>Create with properties</td>
<td><code>const obj = { key: value }</code></td>
</tr>
<tr>
<td>Access</td>
<td><code>obj.key</code></td>
</tr>
<tr>
<td>Dynamic access</td>
<td><code>obj[key]</code></td>
</tr>
<tr>
<td>Update</td>
<td><code>obj.key = value</code></td>
</tr>
<tr>
<td>Add</td>
<td><code>obj.newKey = value</code></td>
</tr>
<tr>
<td>Delete</td>
<td><code>delete obj.key</code></td>
</tr>
<tr>
<td>Get keys</td>
<td><code>Object.keys(obj)</code></td>
</tr>
<tr>
<td>Loop through keys</td>
<td><code>for (const key of Object.keys(obj))</code></td>
</tr>
</tbody></table>
<hr />
<h2>Key Takeaway</h2>
<p>JavaScript objects provide a natural way to represent <strong>structured, related data</strong> using named properties.</p>
<p>Remember these three ideas:</p>
<ul>
<li><p><strong>Object → represents an entity using named properties</strong></p>
</li>
<li><p><strong>Array → represents an ordered collection</strong></p>
</li>
<li><p><strong>Object + Array → commonly work together for real-world data</strong></p>
</li>
</ul>
<p>Once you understand how to create, access, update, add, delete, and loop through object properties, you'll recognize objects everywhere in JavaScript — from simple programs to APIs and full-scale applications.</p>
<p>The goal isn't to memorize object syntax.</p>
<p>It's to recognize when your data naturally looks like:</p>
<pre><code class="language-text">Entity
 ├── property → value
 ├── property → value
 └── property → value
</code></pre>
<p>That's the mental model that makes JavaScript objects much easier to work with.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Synchronous vs Asynchronous Code: How JavaScript Handles Waiting]]></title><description><![CDATA[Imagine your JavaScript program needs to fetch data from an API.
The request might take a few milliseconds—or a few seconds.
Does JavaScript stop everything and wait for the response?
Not necessarily.]]></description><link>https://maazzz.hashnode.dev/javascript-synchronous-vs-asynchronous-code-how-javascript-handles-waiting</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-synchronous-vs-asynchronous-code-how-javascript-handles-waiting</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Mon, 31 Aug 2026 18:33:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/4dafcf8b-7128-4862-9f14-e8dcf10e507b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine your JavaScript program needs to fetch data from an API.</p>
<p>The request might take a few milliseconds—or a few seconds.</p>
<p>Does JavaScript stop everything and wait for the response?</p>
<p><strong>Not necessarily.</strong></p>
<p>Understanding what happens when JavaScript encounters a task that takes time is the key to understanding <strong>synchronous and asynchronous code</strong>.</p>
<p>In this guide, we'll break down:</p>
<ul>
<li><p>What synchronous code means</p>
</li>
<li><p>What asynchronous code means</p>
</li>
<li><p>Why JavaScript needs asynchronous behavior</p>
</li>
<li><p>Blocking vs non-blocking execution</p>
</li>
<li><p>What happens with timers and API requests</p>
</li>
<li><p>Why blocking code can make applications feel frozen</p>
</li>
<li><p>A simple mental model for understanding JavaScript's execution flow</p>
</li>
</ul>
<hr />
<h2>1. Start With Synchronous Code</h2>
<p>Let's start with the simplest case.</p>
<p>Consider:</p>
<pre><code class="language-js">console.log("First");
console.log("Second");
console.log("Third");
</code></pre>
<p>The output is:</p>
<pre><code class="language-text">First
Second
Third
</code></pre>
<p>Why?</p>
<p>Because JavaScript executes these statements <strong>one after another</strong>.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Start
  ↓
First
  ↓
Second
  ↓
Third
  ↓
End
</code></pre>
<p>The next statement doesn't execute until the current one has finished.</p>
<p>This is <strong>synchronous execution</strong>.</p>
<blockquote>
<p><strong>Synchronous code executes in sequence, with each operation completing before the next one proceeds.</strong></p>
</blockquote>
<hr />
<h2>2. What Does "Blocking" Mean?</h2>
<p>Now consider an operation that takes a long time.</p>
<pre><code class="language-js">doSomethingThatTakesALongTime();

console.log("Done");
</code></pre>
<p>If <code>doSomethingThatTakesALongTime()</code> occupies JavaScript's execution thread, JavaScript cannot move to:</p>
<pre><code class="language-js">console.log("Done");
</code></pre>
<p>until that operation finishes.</p>
<p>That's <strong>blocking behavior</strong>.</p>
<p>Think of it like a single checkout counter:</p>
<pre><code class="language-text">Customer A
   ↓
Checkout
   ↓
Customer B
   ↓
Checkout
   ↓
Customer C
</code></pre>
<p>If Customer A takes ten minutes, everyone behind them waits.</p>
<p>Similarly, a long-running synchronous operation can prevent other JavaScript work from executing.</p>
<hr />
<h2>3. Why Blocking Is a Problem</h2>
<p>Imagine a browser running your application.</p>
<p>While JavaScript is busy performing a long synchronous task, it may not be able to process other JavaScript work such as:</p>
<ul>
<li><p>User interactions</p>
</li>
<li><p>Event handlers</p>
</li>
<li><p>UI updates</p>
</li>
<li><p>Other scheduled callbacks</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-js">console.log("Start");

while (true) {
  // Infinite loop
}

console.log("End");
</code></pre>
<p><code>"End"</code> is never reached.</p>
<p>More importantly, the JavaScript thread remains occupied indefinitely.</p>
<p>In a browser, this can make the page appear <strong>frozen or unresponsive</strong>.</p>
<p>So we need a way to start tasks that take time <strong>without making the entire application wait unnecessarily</strong>.</p>
<p>That's where asynchronous behavior becomes important.</p>
<hr />
<h2>4. What Is Asynchronous Code?</h2>
<p>Asynchronous code allows an operation to begin without requiring the rest of the program to wait for that operation to finish before continuing.</p>
<p>For example:</p>
<pre><code class="language-js">console.log("Start");

setTimeout(() =&gt; {
  console.log("Timer finished");
}, 2000);

console.log("End");
</code></pre>
<p>The output is:</p>
<pre><code class="language-text">Start
End
Timer finished
</code></pre>
<p>Notice something important:</p>
<pre><code class="language-text">Start
  ↓
Start timer
  ↓
End
  ↓
...time passes...
  ↓
Timer callback runs
</code></pre>
<p>JavaScript didn't sit there for two seconds before executing <code>"End"</code>.</p>
<p>Instead, the timer was scheduled, and JavaScript continued with other work.</p>
<hr />
<h2>5. An Everyday Example</h2>
<p>Imagine you're at a restaurant.</p>
<h3>Synchronous approach</h3>
<p>You order food and stand at the kitchen counter until it's ready.</p>
<pre><code class="language-text">Order food
    ↓
Stand and wait
    ↓
Food ready
    ↓
Continue
</code></pre>
<p>You can't do anything else while waiting.</p>
<h3>Asynchronous approach</h3>
<p>You order food, receive a number, and sit down.</p>
<pre><code class="language-text">Order food
    ↓
Receive number
    ↓
Do something else
    ↓
Food becomes ready
    ↓
Get notified
</code></pre>
<p>The waiting still happens.</p>
<p>The difference is that <strong>you aren't blocking everything else while waiting</strong>.</p>
<p>That's the intuition behind asynchronous programming.</p>
<hr />
<h2>6. Timers Are a Simple Example</h2>
<p>Consider:</p>
<pre><code class="language-js">console.log("A");

setTimeout(() =&gt; {
  console.log("B");
}, 1000);

console.log("C");
</code></pre>
<p>The output is:</p>
<pre><code class="language-text">A
C
B
</code></pre>
<p>A common beginner misconception is:</p>
<blockquote>
<p>"<code>setTimeout(..., 1000)</code> means JavaScript waits exactly one second and then executes the callback."</p>
</blockquote>
<p>That's not quite correct.</p>
<p>The <code>1000</code> milliseconds specifies a <strong>minimum delay before the callback can be executed</strong>.</p>
<p>It does not guarantee that the callback runs exactly at the one-second mark.</p>
<p>The callback must wait until JavaScript can execute it.</p>
<hr />
<h2>7. What About API Calls?</h2>
<p>API requests are another important example.</p>
<p>Suppose your application needs user data:</p>
<pre><code class="language-js">fetch("/api/users")
  .then(response =&gt; response.json())
  .then(users =&gt; {
    console.log(users);
  });

console.log("Request started");
</code></pre>
<p>The network request may take time.</p>
<p>Instead of blocking JavaScript while waiting for the server, the request is handled asynchronously.</p>
<p>Conceptually:</p>
<pre><code class="language-text">JavaScript
    │
    ├── Start API request ────────→ Server
    │
    ├── Continue other work
    │
    ├── Continue other work
    │
    ←──── Response arrives
    │
    └── Process response
</code></pre>
<p>This is extremely important for web applications because network operations naturally involve waiting.</p>
<hr />
<h2>8. Synchronous vs Asynchronous</h2>
<p>Here's the core difference:</p>
<table>
<thead>
<tr>
<th>Synchronous</th>
<th>Asynchronous</th>
</tr>
</thead>
<tbody><tr>
<td>Executes sequentially</td>
<td>Allows work to continue while an async operation is pending</td>
</tr>
<tr>
<td>Current operation completes before proceeding</td>
<td>Completion is handled later</td>
</tr>
<tr>
<td>Can block the JavaScript thread</td>
<td>Helps avoid blocking while waiting for external work</td>
</tr>
<tr>
<td>Simple and predictable for sequential tasks</td>
<td>Useful for timers, network requests, I/O, and events</td>
</tr>
</tbody></table>
<p>A useful mental model:</p>
<pre><code class="language-text">Synchronous

Task A → Task B → Task C
         ↓
      must wait


Asynchronous

Start Task A ─────────→ completion
      ↓
Continue Task B
      ↓
Continue Task C
      ↓
Handle Task A result
</code></pre>
<hr />
<h2>9. How Does JavaScript Do This?</h2>
<p>Here's where the <strong>event loop</strong> becomes important.</p>
<p>JavaScript execution itself is commonly described around a single call stack, but asynchronous behavior is enabled by the surrounding runtime.</p>
<p>In a browser, APIs such as timers, networking, and DOM events are provided by the browser environment.</p>
<p>In Node.js, similar asynchronous capabilities are provided by the Node.js runtime.</p>
<p>The simplified flow looks like this:</p>
<pre><code class="language-text">JavaScript code
      ↓
   Call Stack
      ↓
Runtime handles asynchronous operation
      ↓
Operation completes
      ↓
Callback becomes eligible to run
      ↓
Event Loop
      ↓
Call Stack
</code></pre>
<p>For example:</p>
<pre><code class="language-js">console.log("Start");

setTimeout(() =&gt; {
  console.log("Timer");
}, 0);

console.log("End");
</code></pre>
<p>Even with <code>0</code> milliseconds, the timer callback doesn't execute immediately.</p>
<p>The synchronous code finishes first:</p>
<pre><code class="language-text">Start
End
Timer
</code></pre>
<p>The callback is scheduled to run later when the runtime and event loop can process it.</p>
<hr />
<h2>10. The Task Queue</h2>
<p>A simplified visualization is:</p>
<pre><code class="language-text">              JavaScript
                  │
                  ↓
             Call Stack
                  │
                  ├──── synchronous code
                  │
                  ↓
        Asynchronous operation
          ↙                 ↘
       Timer              Network
          │                 │
          └───────┬─────────┘
                  ↓
             Queue / Jobs
                  ↓
             Event Loop
                  ↓
             Call Stack
</code></pre>
<p>This is a simplified model—not a complete description of every queue and scheduling rule in JavaScript.</p>
<p>For example, <strong>Promise callbacks use the microtask queue</strong>, which has different scheduling behavior from timer callbacks.</p>
<p>But the key idea is:</p>
<blockquote>
<p>Asynchronous work can finish later, and its JavaScript continuation runs when the runtime schedules it and the call stack is available.</p>
</blockquote>
<hr />
<h2>11. Asynchronous Doesn't Mean "Runs in Parallel"</h2>
<p>This distinction is important.</p>
<p>Asynchronous programming does <strong>not automatically mean JavaScript executes two pieces of JavaScript code simultaneously</strong>.</p>
<p>For example:</p>
<pre><code class="language-js">console.log("A");

setTimeout(() =&gt; {
  console.log("B");
}, 0);

console.log("C");
</code></pre>
<p>You still get:</p>
<pre><code class="language-text">A
C
B
</code></pre>
<p>The JavaScript callback doesn't interrupt the currently executing synchronous code.</p>
<p>Asynchronous programming is primarily about <strong>not blocking while waiting for an operation to complete</strong>.</p>
<p>Actual parallel execution is a separate concept and can involve mechanisms such as Web Workers or Node.js worker threads.</p>
<hr />
<h2>12. Why JavaScript Needs Asynchronous Behavior</h2>
<p>Modern applications constantly perform operations that involve waiting:</p>
<ul>
<li><p>Fetching API data</p>
</li>
<li><p>Reading files</p>
</li>
<li><p>Database operations</p>
</li>
<li><p>Timers</p>
</li>
<li><p>Receiving user events</p>
</li>
<li><p>Network communication</p>
</li>
<li><p>Waiting for external services</p>
</li>
</ul>
<p>If JavaScript blocked the main thread for every one of these operations, applications could become extremely unresponsive.</p>
<p>Imagine:</p>
<pre><code class="language-text">Request data
    ↓
Wait 2 seconds
    ↓
Update UI
    ↓
Request more data
    ↓
Wait again
</code></pre>
<p>During those waits, useful work could be unnecessarily delayed.</p>
<p>Asynchronous APIs allow the runtime to handle the waiting while JavaScript can continue processing other work.</p>
<hr />
<h2>13. Synchronous vs Asynchronous</h2>
<p>Don't think:</p>
<blockquote>
<p>"Synchronous is bad and asynchronous is good."</p>
</blockquote>
<p>That's not true.</p>
<p>Synchronous code is often exactly what you want:</p>
<pre><code class="language-js">const total = price + tax;
const name = user.name;
</code></pre>
<p>These operations are quick and naturally sequential.</p>
<p>Asynchronous programming becomes valuable when an operation involves <strong>waiting for something that isn't immediately available</strong>.</p>
<p>So the better question is:</p>
<blockquote>
<p><strong>"Does this operation need to wait, and should that waiting block other work?"</strong></p>
</blockquote>
<p>If the answer is yes, asynchronous APIs are often the appropriate solution.</p>
<hr />
<h2>14. One Important Distinction</h2>
<p><strong>Synchronous/asynchronous</strong> and <strong>blocking/non-blocking</strong> are related concepts, but they aren't identical.</p>
<ul>
<li><p><strong>Synchronous</strong> describes how execution is coordinated: the next step waits for the current operation to finish.</p>
</li>
<li><p><strong>Asynchronous</strong> means the operation's completion can be handled later, allowing other work to proceed.</p>
</li>
<li><p><strong>Blocking</strong> means the current thread cannot continue with other work while the operation is occupying it.</p>
</li>
<li><p><strong>Non-blocking</strong> means the thread can continue doing other work instead of waiting for that operation to finish.</p>
</li>
</ul>
<p>This distinction becomes especially important when you start learning <strong>Node.js, promises,</strong> <code>async/await</code><strong>, the event loop, and backend I/O</strong>.</p>
<hr />
<h2>15. Quick Cheat Sheet</h2>
<pre><code class="language-text">Synchronous
→ One step finishes before the next proceeds.

Asynchronous
→ Start work and handle its completion later.

Blocking
→ The current thread is prevented from continuing.

Non-blocking
→ The current thread can continue while waiting.
</code></pre>
<p>And remember:</p>
<pre><code class="language-text">API request
   ↓
Start request
   ↓
Don't block JavaScript waiting
   ↓
Continue other work
   ↓
Response arrives
   ↓
Handle the result
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>Synchronous and asynchronous code are fundamental to understanding modern JavaScript.</p>
<p>The simplest way to remember the difference is:</p>
<blockquote>
<p><strong>Synchronous code waits for the current operation before moving forward.</strong></p>
</blockquote>
<blockquote>
<p><strong>Asynchronous code allows the program to continue while waiting for an operation to complete.</strong></p>
</blockquote>
<p>This becomes especially important for operations such as network requests, timers, file I/O, and other tasks that don't finish immediately.</p>
<p>And remember one final distinction:</p>
<p><strong>Asynchronous does not automatically mean parallel.</strong></p>
<p>JavaScript can remain responsive by coordinating asynchronous work through the runtime and event loop, even though JavaScript execution itself is not automatically running multiple callbacks simultaneously.</p>
<p>Once this mental model clicks, concepts like <strong>Promises,</strong> <code>async/await</code><strong>, the event loop, callbacks, and API requests</strong> become much easier to understand.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Map and Set Explained: Store Data Smarter]]></title><description><![CDATA[If you've worked with JavaScript, you've probably used objects for key-value data and arrays for lists.
They're powerful, but sometimes you're forcing them to solve a problem they weren't specifically]]></description><link>https://maazzz.hashnode.dev/javascript-map-and-set-explained-store-data-smarter</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-map-and-set-explained-store-data-smarter</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Thu, 27 Aug 2026 19:19:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/665b2158-3b1b-4a88-ac0d-f153e9eccccf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've worked with JavaScript, you've probably used <strong>objects for key-value data</strong> and <strong>arrays for lists</strong>.</p>
<p>They're powerful, but sometimes you're forcing them to solve a problem they weren't specifically designed for.</p>
<p>What if you need to:</p>
<ul>
<li><p>Store data as <strong>key → value</strong> pairs?</p>
</li>
<li><p>Use objects or other values as keys?</p>
</li>
<li><p>Automatically prevent duplicates?</p>
</li>
<li><p>Frequently check whether something exists?</p>
</li>
<li><p>Make your code clearly express its intent?</p>
</li>
</ul>
<p>That's where JavaScript's <code>Map</code> and <code>Set</code> come in.</p>
<p>In this guide, we'll understand what they are, how they differ from objects and arrays, and when each one is the right choice.</p>
<hr />
<h2>1. What Is a <code>Map</code>?</h2>
<p>A <code>Map</code> is a collection of <strong>key-value pairs</strong>.</p>
<p>Think of it like a lookup table:</p>
<pre><code class="language-text">Key          Value
────────────────────
"user_101" → "Maaz"
"user_102" → "Ali"
"user_103" → "Sara"
</code></pre>
<p>Create one with <code>Map</code>:</p>
<pre><code class="language-js">const users = new Map();

users.set("user_101", "Maaz");
users.set("user_102", "Ali");
</code></pre>
<p>Retrieve a value:</p>
<pre><code class="language-js">users.get("user_101");
// "Maaz"
</code></pre>
<p>Check whether a key exists:</p>
<pre><code class="language-js">users.has("user_101");
// true
</code></pre>
<p>Delete an entry:</p>
<pre><code class="language-js">users.delete("user_101");
</code></pre>
<p>Get the number of entries:</p>
<pre><code class="language-js">users.size;
</code></pre>
<p>The core API is:</p>
<pre><code class="language-text">set()    → add/update
get()    → retrieve
has()    → check
delete() → remove
</code></pre>
<h3>The key idea</h3>
<blockquote>
<p><code>Map</code> <strong>is designed for relationships between keys and values.</strong></p>
</blockquote>
<hr />
<h2>2. Why Use <code>Map</code> Instead of an Object?</h2>
<p>Objects can also store key-value data:</p>
<pre><code class="language-js">const users = {
  user_101: "Maaz",
  user_102: "Ali"
};
</code></pre>
<p>So why use <code>Map</code>?</p>
<p>Because they represent different concepts.</p>
<p>An object is usually used to describe an <strong>entity</strong>:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",
  age: 23
};
</code></pre>
<p>The properties describe the user.</p>
<p>A <code>Map</code> is better when you're managing a <strong>collection of relationships</strong>:</p>
<pre><code class="language-js">const scores = new Map();

scores.set("Maaz", 95);
scores.set("Ali", 87);
</code></pre>
<p>Here, you're modeling:</p>
<pre><code class="language-text">User → Score
</code></pre>
<h3>Important differences</h3>
<table>
<thead>
<tr>
<th>Feature</th>
<th><code>Map</code></th>
<th>Object</th>
</tr>
</thead>
<tbody><tr>
<td>Main purpose</td>
<td>Key-value collection</td>
<td>Entity/properties</td>
</tr>
<tr>
<td>Keys</td>
<td>Almost any value</td>
<td>Strings &amp; symbols</td>
</tr>
<tr>
<td>Size</td>
<td><code>map.size</code></td>
<td><code>Object.keys(obj).length</code></td>
</tr>
<tr>
<td>Add/update</td>
<td><code>set()</code></td>
<td>Assignment</td>
</tr>
<tr>
<td>Read</td>
<td><code>get()</code></td>
<td>Property access</td>
</tr>
<tr>
<td>Check</td>
<td><code>has()</code></td>
<td><code>Object.hasOwn()</code></td>
</tr>
<tr>
<td>Delete</td>
<td><code>delete()</code></td>
<td><code>delete</code></td>
</tr>
<tr>
<td>Iteration</td>
<td>Built for iteration</td>
<td>Object iteration helpers</td>
</tr>
</tbody></table>
<p>A <code>Map</code> can also use an object as a key:</p>
<pre><code class="language-js">const user = { id: 1 };

const roles = new Map();

roles.set(user, "admin");

roles.get(user);
// "admin"
</code></pre>
<p>This is much more natural than trying to use an object as an object property key.</p>
<hr />
<h2>3. Visualizing a <code>Map</code></h2>
<p>A simple mental model:</p>
<pre><code class="language-text">                    MAP

        Key          →        Value

      "user:1"       →        "Maaz"
      "user:2"       →        "Ali"
      "user:3"       →        "Sara"
</code></pre>
<p>This makes <code>Map</code> useful for things like:</p>
<ul>
<li><p>Caches</p>
</li>
<li><p>Lookup tables</p>
</li>
<li><p>Counters</p>
</li>
<li><p>Metadata</p>
</li>
<li><p>Dynamic collections</p>
</li>
<li><p>Object-to-data relationships</p>
</li>
</ul>
<p>For example, a cache naturally looks like:</p>
<pre><code class="language-js">const cache = new Map();

cache.set("/users/1", userData);

const data = cache.get("/users/1");
</code></pre>
<hr />
<h2>4. What Is a <code>Set</code>?</h2>
<p>A <code>Set</code> is a collection of <strong>unique values</strong>.</p>
<p>That's its defining property:</p>
<blockquote>
<p><strong>A value can appear only once in a</strong> <code>Set</code><strong>.</strong></p>
</blockquote>
<pre><code class="language-js">const numbers = new Set();

numbers.add(10);
numbers.add(20);
numbers.add(10);

console.log(numbers);
// Set(2) { 10, 20 }
</code></pre>
<p>The second <code>10</code> is ignored.</p>
<p>Useful operations include:</p>
<pre><code class="language-js">set.add(value);
set.has(value);
set.delete(value);
set.clear();
set.size;
</code></pre>
<p>Unlike an array, a <code>Set</code> isn't designed around indexes.</p>
<p>Its main purpose is <strong>uniqueness and membership</strong>.</p>
<hr />
<h2>5. Why Use <code>Set</code> Instead of an Array?</h2>
<p>Consider this array:</p>
<pre><code class="language-js">const tags = [
  "javascript",
  "node",
  "javascript",
  "react",
  "node"
];
</code></pre>
<p>If you need unique values, you have to handle duplicates yourself.</p>
<p>With <code>Set</code>:</p>
<pre><code class="language-js">const uniqueTags = new Set(tags);
</code></pre>
<p>Now:</p>
<pre><code class="language-text">javascript
node
react
</code></pre>
<p>If you need an array afterward:</p>
<pre><code class="language-js">const uniqueTags = [...new Set(tags)];
</code></pre>
<p>You can also manually enforce uniqueness with an array:</p>
<pre><code class="language-js">if (!users.includes("Maaz")) {
  users.push("Maaz");
}
</code></pre>
<p>But when uniqueness is the actual requirement, <code>Set</code> expresses that requirement directly:</p>
<pre><code class="language-js">const users = new Set();

users.add("Maaz");
users.add("Maaz");
</code></pre>
<p>No duplicate-checking logic is required.</p>
<hr />
<h2>6. Set vs Array</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th><code>Set</code></th>
<th>Array</th>
</tr>
</thead>
<tbody><tr>
<td>Main purpose</td>
<td>Unique values</td>
<td>Ordered/indexed collection</td>
</tr>
<tr>
<td>Duplicates</td>
<td>Prevented</td>
<td>Allowed</td>
</tr>
<tr>
<td>Index access</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Add</td>
<td><code>add()</code></td>
<td><code>push()</code></td>
</tr>
<tr>
<td>Membership</td>
<td><code>has()</code></td>
<td><code>includes()</code></td>
</tr>
<tr>
<td>Size</td>
<td><code>size</code></td>
<td><code>length</code></td>
</tr>
</tbody></table>
<p>Think of them this way:</p>
<pre><code class="language-text">Array
Index → Value

0 → Maaz
1 → Ali
2 → Sara
</code></pre>
<p>versus:</p>
<pre><code class="language-text">Set
Value → Is it present?

Maaz ✓
Ali  ✓
Sara ✓
</code></pre>
<p>So:</p>
<blockquote>
<p><strong>Need position? Think Array.</strong> <strong>Need uniqueness or membership? Think Set.</strong></p>
</blockquote>
<hr />
<h2>7. Visualizing a <code>Set</code></h2>
<pre><code class="language-text">                 SET

          ┌───────────────┐
          │  10  20  30  │
          └───────────────┘
                  ↑
               add(10)
                  │
           Already exists
                  │
               ignored
</code></pre>
<p>The important property isn't indexing.</p>
<p>It's <strong>uniqueness</strong>.</p>
<hr />
<h2>8. A Useful Detail: Objects in a <code>Set</code></h2>
<p><code>Set</code> uses JavaScript's value equality rules.</p>
<p>So this doesn't create one unique object:</p>
<pre><code class="language-js">const set = new Set();

set.add({ id: 1 });
set.add({ id: 1 });

set.size;
// 2
</code></pre>
<p>Why?</p>
<p>Because these are two different object references:</p>
<pre><code class="language-js">{ id: 1 } === { id: 1 }
// false
</code></pre>
<p>If uniqueness should be based on an ID, a <code>Map</code> may be better:</p>
<pre><code class="language-js">const users = new Map();

users.set(1, { id: 1, name: "Maaz" });
users.set(1, { id: 1, name: "Updated Maaz" });

users.size;
// 1
</code></pre>
<p>Now the ID defines the key.</p>
<hr />
<h2>9. When Should You Use <code>Map</code>?</h2>
<p>Choose <code>Map</code> when your problem naturally looks like:</p>
<pre><code class="language-text">Key → Value
</code></pre>
<p>Common examples:</p>
<h3>Caching</h3>
<pre><code class="language-js">cache.set(url, response);
</code></pre>
<h3>Counting</h3>
<pre><code class="language-js">counts.set(
  word,
  (counts.get(word) || 0) + 1
);
</code></pre>
<h3>Object-based keys</h3>
<pre><code class="language-js">metadata.set(user, userMetadata);
</code></pre>
<h3>Dynamic lookups</h3>
<p>When you frequently add, remove, check, retrieve, and iterate over key-value entries, <code>Map</code> is often a clearer choice.</p>
<hr />
<h2>10. When Should You Use <code>Set</code>?</h2>
<p>Choose <code>Set</code> when your problem naturally looks like:</p>
<pre><code class="language-text">Is this value already present?
</code></pre>
<p>Common examples:</p>
<h3>Remove duplicates</h3>
<pre><code class="language-js">const uniqueIds = [...new Set(ids)];
</code></pre>
<h3>Track visited items</h3>
<pre><code class="language-js">const visited = new Set();

if (visited.has(node)) {
  return;
}

visited.add(node);
</code></pre>
<h3>Track selected items</h3>
<pre><code class="language-js">const selectedIds = new Set();

selectedIds.add(101);
selectedIds.add(205);
</code></pre>
<p>Adding <code>101</code> again won't create a duplicate.</p>
<hr />
<h2>11. Map, Set, Object, or Array?</h2>
<p>Use this simple mental model:</p>
<pre><code class="language-text">Need key → value?
       ↓
      Map

Need unique values?
       ↓
      Set

Need an ordered/indexed list?
       ↓
     Array

Need to describe an entity?
       ↓
     Object
</code></pre>
<p>This isn't an absolute rule, but it's an excellent starting point.</p>
<hr />
<h2>12. Quick Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Requirement</th>
<th>Best starting choice</th>
</tr>
</thead>
<tbody><tr>
<td>Key → value collection</td>
<td><code>Map</code></td>
</tr>
<tr>
<td>Unique values</td>
<td><code>Set</code></td>
</tr>
<tr>
<td>Indexed/ordered data</td>
<td><code>Array</code></td>
</tr>
<tr>
<td>Entity with named properties</td>
<td><code>Object</code></td>
</tr>
<tr>
<td>Objects as keys</td>
<td><code>Map</code></td>
</tr>
<tr>
<td>Automatic duplicate prevention</td>
<td><code>Set</code></td>
</tr>
<tr>
<td>Cache / lookup table</td>
<td><code>Map</code></td>
</tr>
<tr>
<td>Visited/selected tracking</td>
<td><code>Set</code></td>
</tr>
</tbody></table>
<hr />
<h2>Conclusion</h2>
<p><code>Map</code> and <code>Set</code> aren't simply "better versions" of objects and arrays.</p>
<p>They solve different problems.</p>
<ul>
<li><p><strong>Object</strong> → represents an entity with named properties.</p>
</li>
<li><p><strong>Array</strong> → represents an ordered, indexed collection.</p>
</li>
<li><p><strong>Map</strong> → represents key → value relationships.</p>
</li>
<li><p><strong>Set</strong> → represents a collection of unique values.</p>
</li>
</ul>
<p>The most useful thing to remember is:</p>
<pre><code class="language-text">Map = Key → Value

Set = Unique Values
</code></pre>
<p>Once you recognize the shape of your data, choosing the right collection becomes much easier.</p>
<p>And that's the real benefit of <code>Map</code> and <code>Set</code>: <strong>less custom logic, clearer intent, and data structures that better match the problem you're solving.</strong></p>
]]></content:encoded></item><item><title><![CDATA[JavaScript this, call(), apply() & bind() ]]></title><description><![CDATA[If you've ever seen JavaScript code like:
this.name

and wondered:

"What exactly is this?"

You're not alone.
this is one of those JavaScript concepts that looks simple but becomes confusing when the]]></description><link>https://maazzz.hashnode.dev/javascript-this-call-apply-bind</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-this-call-apply-bind</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Wed, 26 Aug 2026 19:07:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/8907de11-0010-471f-ad7e-676375d1c87a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've ever seen JavaScript code like:</p>
<pre><code class="language-js">this.name
</code></pre>
<p>and wondered:</p>
<blockquote>
<p><strong>"What exactly is</strong> <code>this</code><strong>?"</strong></p>
</blockquote>
<p>You're not alone.</p>
<p><code>this</code> is one of those JavaScript concepts that looks simple but becomes confusing when the same function is called in different ways.</p>
<p>The good news is that you don't need to understand complicated JavaScript internals to get started.</p>
<p>A powerful beginner-friendly way to think about it is:</p>
<blockquote>
<p><code>this</code> <strong>usually tells us who is calling the function.</strong></p>
</blockquote>
<p>And when we want to control who <code>this</code> refers to, JavaScript gives us three useful methods:</p>
<ul>
<li><p><code>call()</code></p>
</li>
<li><p><code>apply()</code></p>
</li>
<li><p><code>bind()</code></p>
</li>
</ul>
<p>Let's understand all four concepts together.</p>
<hr />
<h2>What Does <code>this</code> Mean?</h2>
<p>Consider this object:</p>
<pre><code class="language-js">const person = {
  name: "Maaz",
  age: 20,

  introduce() {
    console.log(`I'm ${this.name} and I'm ${this.age} years old.`);
  }
};
</code></pre>
<p>Now call the method:</p>
<pre><code class="language-js">person.introduce();
</code></pre>
<p>Who is calling <code>introduce()</code>?</p>
<pre><code class="language-text">person.introduce()
      │
      │ calls
      ↓
 introduce()
      │
      ↓
    this
      │
      ↓
   person
</code></pre>
<p>So:</p>
<pre><code class="language-js">this.name
</code></pre>
<p>means:</p>
<pre><code class="language-js">person.name
</code></pre>
<p>and:</p>
<pre><code class="language-js">this.age
</code></pre>
<p>means:</p>
<pre><code class="language-js">person.age
</code></pre>
<p>Output:</p>
<pre><code class="language-text">I'm Maaz and I'm 20 years old.
</code></pre>
<h3>The mental model</h3>
<p>When you're learning <code>this</code>, ask:</p>
<blockquote>
<p><strong>"Who is calling this function?"</strong></p>
</blockquote>
<p>For an object method:</p>
<pre><code class="language-js">object.method();
</code></pre>
<p>the object before the <code>.</code> is generally the value of <code>this</code>.</p>
<pre><code class="language-text">object.method()
      │
      ↓
   caller
      │
      ↓
    this
</code></pre>
<p>This simple rule will solve many beginner-level <code>this</code> problems.</p>
<hr />
<h2><code>this</code> Inside Normal Functions</h2>
<h2>Now remove the object.</h2>
<pre><code class="language-js">function greet() {
  console.log(this);
}

greet();
</code></pre>
<p>This is a <strong>normal function call</strong>.</p>
<p>There is no object before the function:</p>
<pre><code class="language-js">greet();
</code></pre>
<p>Therefore, <code>this</code> is not automatically the object you might expect.</p>
<p>In strict mode:</p>
<pre><code class="language-js">"use strict";

function greet() {
  console.log(this);
}

greet();
</code></pre>
<p>the result is:</p>
<pre><code class="language-text">undefined
</code></pre>
<p>In non-strict browser code, a regular function call can have <code>this</code> refer to the global object.</p>
<p>So don't memorize:</p>
<blockquote>
<p>"<code>this</code> always equals the caller."</p>
</blockquote>
<p>A better rule is:</p>
<blockquote>
<p><strong>For normal functions,</strong> <code>this</code> <strong>depends on how the function is called.</strong></p>
</blockquote>
<p>That's why this works differently:</p>
<pre><code class="language-js">person.introduce();
</code></pre>
<p>and:</p>
<pre><code class="language-js">introduce();
</code></pre>
<p>The calling style changed.</p>
<hr />
<h2><code>this</code> Inside Objects</h2>
<p>Object methods are where <code>this</code> becomes easiest to understand.</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

user.greet();
</code></pre>
<p>The relationship is:</p>
<pre><code class="language-text">       user
        │
        │ calls
        ↓
      greet()
        │
        ↓
      this
        │
        ↓
       user
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Hello, Maaz
</code></pre>
<p>But here's where JavaScript gets interesting.</p>
<p>What happens if we take the function away from the object?</p>
<pre><code class="language-js">const greetFunction = user.greet;

greetFunction();
</code></pre>
<p>We're no longer doing:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<p>We're doing:</p>
<pre><code class="language-js">greetFunction();
</code></pre>
<p>The calling context has changed.</p>
<pre><code class="language-text">Before:

user.greet()
     ↓
 this = user


After:

greetFunction()
     ↓
Different calling context
     ↓
Different `this`
</code></pre>
<p>This is the key reason <code>call()</code>, <code>apply()</code>, and <code>bind()</code> are useful.</p>
<p>They allow us to <strong>control what</strong> <code>this</code> <strong>should refer to</strong>.</p>
<p><strong>For a deeper dive, read</strong> <a href="https://maazzz.hashnode.dev/javascript-this-keyword-explained-simply?utm_source=hashnode&amp;utm_medium=feed"><strong>this blog</strong></a> <strong>post.</strong></p>
<hr />
<h2>Why Do We Need <code>call()</code>, <code>apply()</code> and <code>bind()</code>?</h2>
<p>Imagine we have a function:</p>
<pre><code class="language-js">function introduce() {
  console.log(`I'm ${this.name}`);
}
</code></pre>
<p>The function expects <code>this.name</code>.</p>
<p>But by itself, it doesn't know which person's <code>name</code> we want.</p>
<p>We can explicitly tell JavaScript:</p>
<blockquote>
<p>"For this function call, use this object as <code>this</code>."</p>
</blockquote>
<p>That's exactly what <code>call()</code> and <code>apply()</code> help us do.</p>
<p>And <code>bind()</code> lets us create a <strong>new function with</strong> <code>this</code> <strong>permanently set to the object we choose</strong>.</p>
<hr />
<h2>What Does <code>call()</code> Do?</h2>
<p>The <code>call()</code> method allows us to call a function while explicitly choosing what <code>this</code> should refer to.</p>
<p>Syntax:</p>
<pre><code class="language-js">function.call(thisValue, arg1, arg2, ...);
</code></pre>
<p>Let's use a simple example:</p>
<pre><code class="language-js">function introduce() {
  console.log(`I'm ${this.name} and I'm ${this.age} years old.`);
}

const person = {
  name: "Maaz",
  age: 20
};

introduce.call(person);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">I'm Maaz and I'm 20 years old.
</code></pre>
<p>What happened?</p>
<pre><code class="language-text">introduce.call(person)
          │
          ↓
    this = person
          │
          ↓
   introduce() runs
</code></pre>
<p>So <code>call()</code> basically lets us say:</p>
<blockquote>
<p><strong>"Call this function and use this object as</strong> <code>this</code><strong>."</strong></p>
</blockquote>
<hr />
<h2>Passing Arguments With <code>call()</code></h2>
<p><code>call()</code> can also pass arguments individually.</p>
<pre><code class="language-js">function introduce(city, profession) {
  console.log(
    `I'm ${this.name} from ${city}. I work as a ${profession}.`
  );
}

const person = {
  name: "Maaz"
};

introduce.call(person, "Multan", "Software Engineer");
</code></pre>
<p>Output:</p>
<pre><code class="language-text">I'm Maaz from Multan. I work as a Software Engineer.
</code></pre>
<p>The structure is:</p>
<pre><code class="language-text">call(
  thisValue,
  argument1,
  argument2
)
</code></pre>
<p>For example:</p>
<pre><code class="language-js">introduce.call(person, "Multan", "Software Engineer");
                  │         │          │
                  │         └──────────┴── arguments
                  │
                  └── this
</code></pre>
<hr />
<h2>What Does <code>apply()</code> Do?</h2>
<p><code>apply()</code> is very similar to <code>call()</code>.</p>
<p>It also:</p>
<ol>
<li><p>Calls the function immediately.</p>
</li>
<li><p>Lets you choose what <code>this</code> refers to.</p>
</li>
</ol>
<p>The main difference is <strong>how arguments are provided</strong>.</p>
<p>With <code>call()</code>:</p>
<pre><code class="language-js">introduce.call(person, "Multan", "Software Engineer");
</code></pre>
<p>Arguments are passed individually.</p>
<p>With <code>apply()</code>:</p>
<pre><code class="language-js">introduce.apply(
  person,
  ["Multan", "Software Engineer"]
);
</code></pre>
<p>Arguments are passed inside an <strong>array</strong> (more precisely, an array-like argument list).</p>
<p>Example:</p>
<pre><code class="language-js">function introduce(city, profession) {
  console.log(
    `I'm ${this.name} from ${city}. I work as a ${profession}.`
  );
}

const person = {
  name: "Maaz"
};

const details = ["Multan", "Software Engineer"];

introduce.apply(person, details);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">I'm Maaz from Multan. I work as a Software Engineer.
</code></pre>
<p>Think of it like this:</p>
<pre><code class="language-text">call()
  │
  ├── this
  ├── argument 1
  └── argument 2


apply()
  │
  ├── this
  └── [argument 1, argument 2]
</code></pre>
<hr />
<h2><code>call()</code> vs <code>apply()</code></h2>
<p>The easiest way to remember the difference:</p>
<pre><code class="language-text">call()
→ arguments separately

apply()
→ arguments in an array
</code></pre>
<p>Example:</p>
<pre><code class="language-js">// call
fn.call(obj, 10, 20);

// apply
fn.apply(obj, [10, 20]);
</code></pre>
<p>Both call the function immediately.</p>
<p>Both allow you to control <code>this</code>.</p>
<p>Only the argument format is different.</p>
<hr />
<h2>What Does <code>bind()</code> Do?</h2>
<p>Now comes the important difference.</p>
<p><code>bind()</code> does <strong>not immediately call the function</strong>.</p>
<p>Instead, it creates a <strong>new function</strong> with <code>this</code> set to the object you provide.</p>
<p>Example:</p>
<pre><code class="language-js">function introduce() {
  console.log(`I'm ${this.name}`);
}

const person = {
  name: "Maaz"
};

const boundIntroduce = introduce.bind(person);
</code></pre>
<p>Nothing has been printed yet.</p>
<p>Why?</p>
<p>Because <code>bind()</code> only creates the new function.</p>
<p>We call it later:</p>
<pre><code class="language-js">boundIntroduce();
</code></pre>
<p>Output:</p>
<pre><code class="language-text">I'm Maaz
</code></pre>
<p>The flow is:</p>
<pre><code class="language-text">introduce.bind(person)
          │
          ↓
   New function created
          │
          ↓
   boundIntroduce
          │
          │ later
          ↓
   boundIntroduce()
          │
          ↓
     this = person
</code></pre>
<p>This is the biggest difference between <code>bind()</code> and the other two.</p>
<hr />
<h2>A Realistic <code>bind()</code> Example</h2>
<p><code>bind()</code> becomes especially useful when a function needs to be passed somewhere else but still needs the correct <code>this</code>.</p>
<p>For example:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

const greetUser = user.greet.bind(user);

greetUser();
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Hello, Maaz
</code></pre>
<p>We created a new function that remembers:</p>
<pre><code class="language-text">this → user
</code></pre>
<p>Even though we're calling:</p>
<pre><code class="language-js">greetUser();
</code></pre>
<p>instead of:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<hr />
<h2>The Big Difference: <code>call()</code> vs <code>apply()</code> vs <code>bind()</code></h2>
<p>Here's the comparison you should remember:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Calls immediately?</th>
<th>How arguments are passed</th>
<th>Main purpose</th>
</tr>
</thead>
<tbody><tr>
<td><code>call()</code></td>
<td>✅ Yes</td>
<td>Individually</td>
<td>Call with a specific <code>this</code></td>
</tr>
<tr>
<td><code>apply()</code></td>
<td>✅ Yes</td>
<td>Array</td>
<td>Call with a specific <code>this</code></td>
</tr>
<tr>
<td><code>bind()</code></td>
<td>❌ No</td>
<td>Individually</td>
<td>Create a new function with fixed <code>this</code></td>
</tr>
</tbody></table>
<p>The visual version:</p>
<pre><code class="language-text">                 Function
                    │
          ┌─────────┼─────────┐
          ↓         ↓         ↓
        call()    apply()    bind()
          │         │         │
          ↓         ↓         ↓
       Execute    Execute    Create
       now        now        new function
          │         │         │
      args:       args:      this:
      separate   array       fixed
</code></pre>
<hr />
<h2>One Example Showing All Three</h2>
<p>Let's make the difference crystal clear.</p>
<pre><code class="language-js">function introduce(city, job) {
  console.log(
    `${this.name} lives in ${city} and works as a ${job}.`
  );
}

const person = {
  name: "Maaz"
};
</code></pre>
<h3>Using <code>call()</code></h3>
<pre><code class="language-js">introduce.call(
  person,
  "Multan",
  "Software Engineer"
);
</code></pre>
<p><strong>Calls immediately.</strong></p>
<p>Arguments are separate.</p>
<hr />
<h3>Using <code>apply()</code></h3>
<pre><code class="language-js">introduce.apply(
  person,
  ["Multan", "Software Engineer"]
);
</code></pre>
<p><strong>Calls immediately.</strong></p>
<p>Arguments are inside an array.</p>
<hr />
<h3>Using <code>bind()</code></h3>
<pre><code class="language-js">const introduceMaaz = introduce.bind(
  person,
  "Multan",
  "Software Engineer"
);

introduceMaaz();
</code></pre>
<p><strong>Doesn't call immediately.</strong></p>
<p>Instead, it creates a new function that remembers the provided <code>this</code> and arguments.</p>
<hr />
<h2>A Simple Memory Trick</h2>
<p>If you forget everything else, remember:</p>
<pre><code class="language-text">CALL
→ Call it now
→ Arguments separately

APPLY
→ Apply it now
→ Arguments as an array

BIND
→ Bind it for later
→ Returns a new function
</code></pre>
<p>Or:</p>
<blockquote>
<p><strong>Call = now</strong> <strong>Apply = now + array</strong> <strong>Bind = later</strong></p>
</blockquote>
<hr />
<h2>Borrowing Methods With <code>call()</code></h2>
<p>One useful feature of <code>call()</code> is <strong>method borrowing</strong>.</p>
<p>Imagine:</p>
<pre><code class="language-js">const person1 = {
  name: "Maaz",

  greet() {
    console.log(`Hello, ${this.name}`);
  }
};

const person2 = {
  name: "Ali"
};
</code></pre>
<p><code>person2</code> doesn't have a <code>greet()</code> method.</p>
<p>But we can borrow <code>person1</code>'s method:</p>
<pre><code class="language-js">person1.greet.call(person2);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Hello, Ali
</code></pre>
<p>Why?</p>
<p>Because we explicitly changed <code>this</code>:</p>
<pre><code class="language-text">person1.greet
      │
      │ call(person2)
      ↓
  this = person2
      │
      ↓
Hello, Ali
</code></pre>
<p>The function comes from <code>person1</code>, but during this call, <code>this</code> refers to <code>person2</code>.</p>
<p>That's the power of explicitly controlling the calling context.</p>
<hr />
<h2>Your Practice Assignment</h2>
<p>Try this yourself before looking back at the examples.</p>
<h3>Step 1 — Create an object</h3>
<p>Create an object with:</p>
<ul>
<li><p><code>name</code></p>
</li>
<li><p><code>age</code></p>
</li>
<li><p>a <code>introduce()</code> method using <code>this</code></p>
</li>
</ul>
<p>For example, your object should conceptually look like:</p>
<pre><code class="language-text">person
├── name
├── age
└── introduce()
</code></pre>
<h3>Step 2 — Borrow the method with <code>call()</code></h3>
<p>Create another object and use:</p>
<pre><code class="language-js">person.introduce.call(otherPerson);
</code></pre>
<p>Observe which person's data is printed.</p>
<h3>Step 3 — Use <code>apply()</code></h3>
<p>Create a function that accepts two arguments.</p>
<p>Call it using:</p>
<pre><code class="language-js">functionName.apply(object, [arg1, arg2]);
</code></pre>
<h3>Step 4 — Use <code>bind()</code></h3>
<p>Create a new function:</p>
<pre><code class="language-js">const newFunction = functionName.bind(object);
</code></pre>
<p>Then call it later.</p>
<p>Your goal is to understand what changes when you change the <strong>calling context</strong>.</p>
<hr />
<h2>The Mental Model to Keep</h2>
<p>When you encounter <code>this</code>, start with one question:</p>
<blockquote>
<p><strong>"How is this function being called?"</strong></p>
</blockquote>
<p>Then remember:</p>
<pre><code class="language-text">object.method()
      ↓
this → object
</code></pre>
<p>If you want to manually control <code>this</code>:</p>
<pre><code class="language-text">call()
  ↓
Call now + separate arguments


apply()
  ↓
Call now + array arguments


bind()
  ↓
Create a new function for later
</code></pre>
<p>And the complete relationship becomes:</p>
<pre><code class="language-text">                    FUNCTION
                       │
            ┌──────────┴──────────┐
            ↓                     ↓
       Normal call          Explicit control
            │                     │
            ↓              ┌──────┼──────┐
     depends on how       call() apply() bind()
     it is called           │       │       │
                            ↓       ↓       ↓
                           now     now    later
</code></pre>
<hr />
<h1><strong>What to Remember</strong></h1>
<p>JavaScript's <code>this</code> becomes much easier when you stop treating it as a mysterious keyword.</p>
<p>Think about the <strong>calling context</strong>.</p>
<p>When an object calls a method:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<p><code>this</code> generally refers to <code>user</code>.</p>
<p>When you need to explicitly control <code>this</code>, JavaScript gives you:</p>
<pre><code class="language-js">call()
apply()
bind()
</code></pre>
<p>The difference is simple:</p>
<pre><code class="language-text">call()
→ immediately calls the function
→ arguments separately

apply()
→ immediately calls the function
→ arguments as an array

bind()
→ does not call immediately
→ returns a new function
→ remembers the chosen `this`
</code></pre>
<p>The most important thing to remember is:</p>
<blockquote>
<p><code>call()</code> <strong>and</strong> <code>apply()</code> <strong>call a function now.</strong> <code>bind()</code> <strong>prepares a function to be called later.</strong></p>
</blockquote>
<p>Once you understand that relationship, <code>this</code>, method borrowing, and function binding become much less confusing—and you'll have a much stronger foundation for understanding JavaScript's more advanced object-oriented patterns.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript this Keyword Explained Simply]]></title><description><![CDATA[If you've written JavaScript for a while, you've probably seen this:
this.name

It looks simple.
Then you put it inside a function and suddenly this becomes undefined, a global object, or something co]]></description><link>https://maazzz.hashnode.dev/javascript-this-keyword-explained-simply</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-this-keyword-explained-simply</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Tue, 25 Aug 2026 20:23:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/4776c3a9-5d19-45f8-8de0-90f09c4738e2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've written JavaScript for a while, you've probably seen this:</p>
<pre><code class="language-js">this.name
</code></pre>
<p>It looks simple.</p>
<p>Then you put it inside a function and suddenly <code>this</code> becomes <code>undefined</code>, a global object, or something completely different.</p>
<p>Why?</p>
<p>Because one of the most common explanations of <code>this</code> is also one of the most misleading:</p>
<blockquote>
<p>"<code>this</code> refers to the current object."</p>
</blockquote>
<p>That's only sometimes true.</p>
<p>A much better mental model is:</p>
<blockquote>
<p><strong>For regular functions,</strong> <code>this</code> <strong>is determined by how the function is called.</strong></p>
</blockquote>
<p>And there's one major exception:</p>
<blockquote>
<p><strong>Arrow functions don't have their own</strong> <code>this</code><strong>; they inherit it from their surrounding scope.</strong></p>
</blockquote>
<p>Once you understand those two ideas, most <code>this</code> behavior becomes predictable.</p>
<hr />
<h2>The Core Mental Model</h2>
<p>For a <strong>regular function</strong>, first look at the call:</p>
<pre><code class="language-text">How was the function called?
          │
    ┌─────┼──────────┐
    ↓     ↓          ↓
object.  fn()       new Fn()
method()
    │     │          │
    ↓     ↓          ↓
 object  depends    new object
         on mode
</code></pre>
<p>But for an <strong>arrow function</strong>:</p>
<pre><code class="language-text">Arrow function
      │
      ↓
Doesn't create its own `this`
      │
      ↓
Uses surrounding `this`
</code></pre>
<p>This distinction explains most of JavaScript's <code>this</code>.</p>
<hr />
<h2><code>this</code> in an Object Method</h2>
<p>The easiest case:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(this.name);
  }
};

user.greet();
</code></pre>
<p>The function is called as:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<p>Therefore:</p>
<pre><code class="language-text">user.greet()
     ↓
this = user
</code></pre>
<p>So:</p>
<pre><code class="language-js">this.name
</code></pre>
<p>is effectively:</p>
<pre><code class="language-js">user.name
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Maaz
</code></pre>
<p>This is why the common pattern:</p>
<pre><code class="language-js">object.method();
</code></pre>
<p>usually gives:</p>
<pre><code class="language-text">this → object
</code></pre>
<hr />
<h2><code>this</code> Is Not Where the Function Was Defined</h2>
<p>Here's the important part.</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(this.name);
  }
};

user.greet();
</code></pre>
<p>works because of the call site.</p>
<p>But:</p>
<pre><code class="language-js">const greet = user.greet;

greet();
</code></pre>
<p>is a different call.</p>
<p>The function is now called as:</p>
<pre><code class="language-js">greet();
</code></pre>
<p>not:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<p>The original receiver is gone.</p>
<p>So don't think:</p>
<blockquote>
<p>"<code>this</code> belongs to the object where the function was created."</p>
</blockquote>
<p>Instead ask:</p>
<blockquote>
<p><strong>"How is this function being called right now?"</strong></p>
</blockquote>
<hr />
<h2>Regular Functions</h2>
<p>The same <code>this</code> rules apply whether you create a regular function using a declaration:</p>
<pre><code class="language-js">function greet() {
  console.log(this);
}
</code></pre>
<p>or a function expression:</p>
<pre><code class="language-js">const greet = function () {
  console.log(this);
};
</code></pre>
<p>Both are <strong>regular functions</strong>.</p>
<p>Their <code>this</code> is determined by how they're invoked.</p>
<p>For example:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet: function () {
    console.log(this.name);
  }
};

user.greet();
</code></pre>
<p>Here:</p>
<pre><code class="language-text">this → user
</code></pre>
<p>The important distinction isn't:</p>
<pre><code class="language-text">function declaration vs function expression
</code></pre>
<p>It's:</p>
<pre><code class="language-text">regular function vs arrow function
</code></pre>
<hr />
<h2><code>this</code> in a Normal Function Call</h2>
<p>Consider:</p>
<pre><code class="language-js">"use strict";

function showThis() {
  console.log(this);
}

showThis();
</code></pre>
<p>There is no object before the function call.</p>
<p>It's simply:</p>
<pre><code class="language-js">showThis();
</code></pre>
<p>In strict mode:</p>
<pre><code class="language-text">this → undefined
</code></pre>
<p>In non-strict classic script code, a normal function call can default <code>this</code> to the global object.</p>
<p>So:</p>
<pre><code class="language-text">Regular function
      │
      ├── strict mode
      │      ↓
      │   undefined
      │
      └── non-strict
             ↓
        global object
</code></pre>
<p>This is why:</p>
<blockquote>
<p>"<code>this</code> always means the caller"</p>
</blockquote>
<p>is not a completely accurate rule.</p>
<p>It's better to say:</p>
<blockquote>
<p><strong>Regular functions get</strong> <code>this</code> <strong>from their invocation pattern.</strong></p>
</blockquote>
<hr />
<h2>Global <code>this</code></h2>
<p>Top-level <code>this</code> is a separate case from function <code>this</code>.</p>
<p>In a traditional browser script:</p>
<pre><code class="language-js">console.log(this === window);
</code></pre>
<p>generally gives:</p>
<pre><code class="language-text">true
</code></pre>
<p>But ES modules behave differently:</p>
<pre><code class="language-js">// module.js

console.log(this);
</code></pre>
<p>At the top level of an ES module:</p>
<pre><code class="language-text">this → undefined
</code></pre>
<p>Node.js can also differ depending on whether you're using CommonJS or ES modules.</p>
<p>So don't memorize:</p>
<pre><code class="language-text">this = window
</code></pre>
<p>as a universal JavaScript rule.</p>
<p>Instead ask:</p>
<pre><code class="language-text">Where is this code running?
Script?
Module?
Function?
Method?
</code></pre>
<hr />
<h2>Arrow Functions: The Big Exception</h2>
<p>Now consider:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet: () =&gt; {
    console.log(this.name);
  }
};

user.greet();
</code></pre>
<p>You might expect:</p>
<pre><code class="language-text">this → user
</code></pre>
<p>But arrow functions don't work that way.</p>
<p>An arrow function <strong>doesn't create its own</strong> <code>this</code>.</p>
<p>Instead, it inherits <code>this</code> from its surrounding lexical scope.</p>
<p>Think:</p>
<pre><code class="language-text">Arrow function
      │
      ↓
No own `this`
      │
      ↓
Look at surrounding scope
      │
      ↓
Use that `this`
</code></pre>
<p>Therefore, an arrow function used as an object method does <strong>not</strong> automatically get the object as <code>this</code>.</p>
<hr />
<h2>Regular Function vs Arrow Function</h2>
<p>Compare:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  regular() {
    console.log(this.name);
  },

  arrow: () =&gt; {
    console.log(this.name);
  }
};

user.regular();
user.arrow();
</code></pre>
<p>The regular method:</p>
<pre><code class="language-text">user.regular()
      ↓
this = user
</code></pre>
<p>The arrow:</p>
<pre><code class="language-text">user.arrow()
      ↓
arrow has no own this
      ↓
uses surrounding this
</code></pre>
<p>This is why, when an object method needs dynamic <code>this</code>, the normal method syntax is usually the better choice:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(this.name);
  }
};
</code></pre>
<p>rather than:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet: () =&gt; {
    console.log(this.name);
  }
};
</code></pre>
<hr />
<h2>Nested Functions: Where Things Get Interesting</h2>
<p>Consider:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    console.log(this.name);

    function inner() {
      console.log(this.name);
    }

    inner();
  }
};

user.greet();
</code></pre>
<p>The outer method is called as:</p>
<pre><code class="language-js">user.greet();
</code></pre>
<p>so:</p>
<pre><code class="language-text">greet()
  ↓
this = user
</code></pre>
<p>But <code>inner()</code> is called separately:</p>
<pre><code class="language-js">inner();
</code></pre>
<p>It's another regular function call.</p>
<p>It does <strong>not</strong> automatically inherit the outer <code>this</code>.</p>
<p>Now change it to an arrow:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    const inner = () =&gt; {
      console.log(this.name);
    };

    inner();
  }
};

user.greet();
</code></pre>
<p>Now the arrow inherits <code>this</code> from <code>greet()</code>:</p>
<pre><code class="language-text">user.greet()
      ↓
this = user
      ↓
inner arrow
      ↓
inherits this
      ↓
user
</code></pre>
<p>This is one of the most practical reasons arrow functions are useful.</p>
<hr />
<h2><code>this</code> in Callbacks</h2>
<p>The same concept appears constantly in asynchronous JavaScript.</p>
<p>This can cause problems:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    setTimeout(function () {
      console.log(this.name);
    }, 1000);
  }
};
</code></pre>
<p>The callback is a separate regular function.</p>
<p>It doesn't automatically inherit the outer method's <code>this</code>.</p>
<p>An arrow callback solves that:</p>
<pre><code class="language-js">const user = {
  name: "Maaz",

  greet() {
    setTimeout(() =&gt; {
      console.log(this.name);
    }, 1000);
  }
};
</code></pre>
<p>Now:</p>
<pre><code class="language-text">greet()
  ↓
this = user
  ↓
arrow callback
  ↓
inherits this
  ↓
user
</code></pre>
<p>This pattern appears frequently with:</p>
<pre><code class="language-text">setTimeout
Promises
array callbacks
event handlers
async code
</code></pre>
<hr />
<h2><code>this</code> in Event Handlers</h2>
<p>Browser event handlers are another important case.</p>
<p>With a regular function:</p>
<pre><code class="language-js">button.addEventListener("click", function () {
  console.log(this);
});
</code></pre>
<p>the browser sets <code>this</code> to the element handling the event.</p>
<p>So:</p>
<pre><code class="language-text">regular event listener
        ↓
this = currentTarget
</code></pre>
<p>With an arrow:</p>
<pre><code class="language-js">button.addEventListener("click", () =&gt; {
  console.log(this);
});
</code></pre>
<p>the arrow doesn't get the button as <code>this</code>.</p>
<p>It inherits <code>this</code> from the surrounding scope.</p>
<p>That's why arrow-based event handlers commonly use:</p>
<pre><code class="language-js">button.addEventListener("click", (event) =&gt; {
  console.log(event.currentTarget);
});
</code></pre>
<p>instead.</p>
<p>Also remember:</p>
<pre><code class="language-text">this / event.currentTarget
        ↓
element whose listener is handling the event

event.target
        ↓
element where the event actually originated
</code></pre>
<p>These aren't always the same element.</p>
<hr />
<h2><code>call()</code>, <code>apply()</code>, and <code>bind()</code></h2>
<p>JavaScript gives you explicit control over <code>this</code>.</p>
<h2><code>call()</code></h2>
<pre><code class="language-js">function greet() {
  console.log(this.name);
}

const user = {
  name: "Maaz"
};

greet.call(user);
</code></pre>
<p>Now:</p>
<pre><code class="language-text">this → user
</code></pre>
<p><code>call()</code> executes the function immediately.</p>
<hr />
<h2><code>apply()</code></h2>
<p><code>apply()</code> works similarly but accepts arguments as an array:</p>
<pre><code class="language-js">function introduce(age, city) {
  console.log(this.name, age, city);
}

introduce.apply(user, [23, "Multan"]);
</code></pre>
<p>Think:</p>
<pre><code class="language-text">call(obj, arg1, arg2)
apply(obj, [arg1, arg2])
</code></pre>
<hr />
<h2><code>bind()</code></h2>
<p><code>bind()</code> doesn't immediately execute the function.</p>
<p>It creates a new function with <code>this</code> bound:</p>
<pre><code class="language-js">const boundGreet = greet.bind(user);

boundGreet();
</code></pre>
<p>Now:</p>
<pre><code class="language-text">boundGreet()
     ↓
this = user
</code></pre>
<p>This is especially useful when passing object methods as callbacks.</p>
<hr />
<h2>Can <code>call()</code> Change Arrow Function <code>this</code>?</h2>
<p>No.</p>
<p>For example:</p>
<pre><code class="language-js">const greet = () =&gt; {
  console.log(this);
};

greet.call(user);
</code></pre>
<p><code>call()</code> cannot replace an arrow function's lexical <code>this</code>.</p>
<p>The same applies to:</p>
<pre><code class="language-js">apply()
bind()
</code></pre>
<p>So:</p>
<pre><code class="language-text">Regular function
call/apply/bind → can control this


Arrow function
call/apply/bind → cannot replace lexical this
</code></pre>
<hr />
<h2><code>this</code> With <code>new</code></h2>
<p>Now consider a constructor function:</p>
<pre><code class="language-js">function Student(name, age) {
  this.name = name;
  this.age = age;
}

const student = new Student("Maaz", 23);
</code></pre>
<p>With <code>new</code>, JavaScript creates a new object and uses that object as <code>this</code>.</p>
<p>A useful simplified model is:</p>
<pre><code class="language-text">new Student(...)
      │
      ↓
create new object
      │
      ↓
link to Student.prototype
      │
      ↓
run constructor with this = object
      │
      ↓
return object
</code></pre>
<p>Therefore:</p>
<pre><code class="language-js">student.name
</code></pre>
<p>gives:</p>
<pre><code class="language-text">Maaz
</code></pre>
<p>The same principle is used by classes:</p>
<pre><code class="language-js">class Student {
  constructor(name) {
    this.name = name;
  }
}

const student = new Student("Maaz");
</code></pre>
<p>Inside the constructor:</p>
<pre><code class="language-text">this → newly created Student instance
</code></pre>
<hr />
<h2><code>this</code> in Class Methods</h2>
<p>Consider:</p>
<pre><code class="language-js">class Student {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(this.name);
  }
}

const student = new Student("Maaz");

student.introduce();
</code></pre>
<p>Because the method is called as:</p>
<pre><code class="language-js">student.introduce();
</code></pre>
<p>we get:</p>
<pre><code class="language-text">this → student
</code></pre>
<p>But if we extract it:</p>
<pre><code class="language-js">const introduce = student.introduce;

introduce();
</code></pre>
<p>the method loses its receiver.</p>
<p>Since class methods are strict-mode functions:</p>
<pre><code class="language-text">this → undefined
</code></pre>
<p>This is a common source of bugs when passing class methods as callbacks.</p>
<hr />
<h2>Static Methods</h2>
<p>Static methods belong to the class rather than an instance:</p>
<pre><code class="language-js">class MathHelper {
  static square(number) {
    return number * number;
  }
}

MathHelper.square(5);
</code></pre>
<p>Inside the static method:</p>
<pre><code class="language-text">this → MathHelper
</code></pre>
<p>So:</p>
<pre><code class="language-text">Instance method
student.introduce()
        ↓
this = student


Static method
MathHelper.square()
        ↓
this = MathHelper
</code></pre>
<hr />
<h2>Getters and Setters</h2>
<p><code>this</code> also works inside getters and setters:</p>
<pre><code class="language-js">const user = {
  firstName: "Maaz",
  lastName: "Hafeez",

  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
};

console.log(user.fullName);
</code></pre>
<p>Here <code>this</code> refers to the object on which the getter is accessed.</p>
<p>Setters work similarly:</p>
<pre><code class="language-js">const user = {
  _name: "",

  set name(value) {
    this._name = value;
  }
};

user.name = "Maaz";
</code></pre>
<p>So <code>this</code> isn't limited to ordinary methods.</p>
<hr />
<h2>A Powerful Example: Method Borrowing</h2>
<p>Regular functions can be reused with different objects.</p>
<pre><code class="language-js">function introduce() {
  console.log(`My name is ${this.name}`);
}

const user1 = {
  name: "Maaz"
};

const user2 = {
  name: "Ali"
};

introduce.call(user1);
introduce.call(user2);
</code></pre>
<p>Output:</p>
<pre><code class="language-text">My name is Maaz
My name is Ali
</code></pre>
<p>Same function.</p>
<p>Different <code>this</code>.</p>
<p>That's the power of JavaScript's dynamic function context.</p>
<hr />
<h2>The <code>this</code> Debugging Checklist</h2>
<p>When <code>this</code> behaves unexpectedly, don't guess.</p>
<p>Ask these questions:</p>
<h3>1. Is it an arrow function?</h3>
<p>If yes:</p>
<pre><code class="language-text">It doesn't have its own this.
Look at the surrounding scope.
</code></pre>
<h3>2. Is it called with <code>new</code>?</h3>
<pre><code class="language-js">new Constructor()
</code></pre>
<p>Then:</p>
<pre><code class="language-text">this → new object
</code></pre>
<h3>3. Is <code>call</code>, <code>apply</code>, or <code>bind</code> involved?</h3>
<p>If it's a regular function, they can explicitly control <code>this</code>.</p>
<h3>4. Is it called as <code>object.method()</code>?</h3>
<p>Then:</p>
<pre><code class="language-text">this → object
</code></pre>
<h3>5. Was the method extracted?</h3>
<p>Look for:</p>
<pre><code class="language-js">const fn = object.method;
</code></pre>
<p>or:</p>
<pre><code class="language-js">const { method } = object;
</code></pre>
<p>The original receiver may have been lost.</p>
<h3>6. Is it a normal function call?</h3>
<pre><code class="language-js">fn();
</code></pre>
<p>Then check strict mode and the runtime.</p>
<p>This checklist is far more useful than memorizing isolated examples.</p>
<hr />
<h2>The <code>this</code> Cheat Sheet</h2>
<table>
<thead>
<tr>
<th>Situation</th>
<th><code>this</code></th>
</tr>
</thead>
<tbody><tr>
<td><code>obj.method()</code></td>
<td><code>obj</code></td>
</tr>
<tr>
<td><code>fn()</code> in strict mode</td>
<td><code>undefined</code></td>
</tr>
<tr>
<td><code>fn()</code> in non-strict classic code</td>
<td>Global object</td>
</tr>
<tr>
<td><code>fn.call(obj)</code></td>
<td><code>obj</code></td>
</tr>
<tr>
<td><code>fn.apply(obj)</code></td>
<td><code>obj</code></td>
</tr>
<tr>
<td><code>fn.bind(obj)</code></td>
<td>Bound to <code>obj</code></td>
</tr>
<tr>
<td><code>new Fn()</code></td>
<td>New object</td>
</tr>
<tr>
<td>Arrow function</td>
<td>Lexical <code>this</code></td>
</tr>
<tr>
<td>Arrow + <code>call/apply/bind</code></td>
<td>Lexical <code>this</code> remains</td>
</tr>
<tr>
<td>Regular DOM listener</td>
<td><code>currentTarget</code></td>
</tr>
<tr>
<td>Arrow DOM listener</td>
<td>Lexical <code>this</code></td>
</tr>
<tr>
<td>ES module top-level</td>
<td><code>undefined</code></td>
</tr>
<tr>
<td>Classic browser script top-level</td>
<td>Global object</td>
</tr>
</tbody></table>
<hr />
<h2>Conclusion</h2>
<p>You don't need to memorize dozens of unrelated rules.</p>
<p>Start with this:</p>
<pre><code class="language-text">                     this
                      │
             ┌────────┴────────┐
             │                 │
       Regular function    Arrow function
             │                 │
             ↓                 ↓
      Check the call      Check outside
             │                 │
      ┌──────┼──────┐          │
      ↓      ↓      ↓          ↓
    obj.     new   call/    surrounding
   method()       apply/      this
                   bind
      │      │       │
      ↓      ↓       ↓
    object  new    explicit
            object   value
</code></pre>
<p>And remember the two rules that matter most:</p>
<blockquote>
<p><strong>Regular functions get their</strong> <code>this</code> <strong>from how they are called.</strong></p>
</blockquote>
<blockquote>
<p><strong>Arrow functions don't have their own</strong> <code>this</code><strong>; they inherit it from their surrounding scope.</strong></p>
</blockquote>
<p>Once you start reading JavaScript by looking at the <strong>function type + call site</strong>, <code>this</code> stops looking random.</p>
<p>It becomes predictable.</p>
<hr />
<h2>Quick Recap</h2>
<pre><code class="language-text">object.method()
      ↓
this = object


fn()
      ↓
strict → undefined
non-strict → global object


fn.call(obj)
fn.apply(obj)
fn.bind(obj)
      ↓
this = obj


new Fn()
      ↓
this = new object


arrow function
      ↓
this = surrounding lexical this
</code></pre>
<p>The next time you see:</p>
<pre><code class="language-js">this
</code></pre>
<p>don't ask:</p>
<blockquote>
<p>"What object is this inside?"</p>
</blockquote>
<p>Ask:</p>
<blockquote>
<p><strong>"What kind of function is this, and how was it called?"</strong></p>
</blockquote>
<p>That question is the key to understanding JavaScript's <code>this</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Object-Oriented Programming (OOP) in JavaScript]]></title><description><![CDATA[If you've ever created a JavaScript object like this:
const student = {
  name: "Maaz",
  age: 20
};

you've already used one of the basic building blocks of Object-Oriented Programming (OOP).
But as ]]></description><link>https://maazzz.hashnode.dev/object-oriented-programming-oop-in-javascript</link><guid isPermaLink="true">https://maazzz.hashnode.dev/object-oriented-programming-oop-in-javascript</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Sun, 23 Aug 2026 19:46:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/b846766b-3b73-4ada-bc79-3b943a707fe1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've ever created a JavaScript object like this:</p>
<pre><code class="language-js">const student = {
  name: "Maaz",
  age: 20
};
</code></pre>
<p>you've already used one of the basic building blocks of <strong>Object-Oriented Programming (OOP)</strong>.</p>
<p>But as applications grow, we often need hundreds of similar objects: students, users, products, cars, orders, and more.</p>
<p>Instead of repeatedly defining the same structure, OOP gives us a better idea:</p>
<blockquote>
<p><strong>Create a blueprint once, then use that blueprint to create as many objects as you need.</strong></p>
</blockquote>
<p>In this beginner-friendly guide, we'll understand <strong>OOP in JavaScript from the ground up</strong> using simple examples and visual representations.</p>
<hr />
<h2>What Is Object-Oriented Programming?</h2>
<p><strong>Object-Oriented Programming (OOP)</strong> is a way of organizing code around <strong>objects</strong>.</p>
<p>An object usually contains two things:</p>
<ul>
<li><p><strong>Properties</strong> → information/data</p>
</li>
<li><p><strong>Methods</strong> → actions/behavior</p>
</li>
</ul>
<p>For example, think about a <code>Car</code>.</p>
<pre><code class="language-text">CAR
├── Properties
│   ├── brand
│   ├── model
│   └── color
│
└── Methods
    ├── start()
    ├── drive()
    └── stop()
</code></pre>
<p>So instead of keeping a car's data in one place and its related functions somewhere else, OOP lets us organize them together.</p>
<p>A simple mental model is:</p>
<pre><code class="language-text">             OBJECT
        ┌─────────────┐
        │    DATA     │
        │ brand       │
        │ model       │
        ├─────────────┤
        │  BEHAVIOR   │
        │ start()     │
        │ drive()     │
        └─────────────┘
</code></pre>
<p>That's the basic idea behind OOP.</p>
<hr />
<h2>The Best Analogy: Blueprint → Objects</h2>
<p>Imagine an architect creates a <strong>house blueprint</strong>.</p>
<p>The blueprint might describe:</p>
<pre><code class="language-text">HOUSE BLUEPRINT
├── rooms
├── doors
├── windows
└── methods/behavior
</code></pre>
<p>The blueprint itself isn't a house.</p>
<p>It is a <strong>plan for creating houses</strong>.</p>
<p>From that blueprint, we can build many houses:</p>
<pre><code class="language-text">                    BLUEPRINT
                  ┌─────────────┐
                  │ House       │
                  │ rooms       │
                  │ doors       │
                  │ windows     │
                  └──────┬──────┘
                         │
             ┌───────────┼───────────┐
             ↓           ↓           ↓
          House 1     House 2     House 3
          3 rooms     5 rooms     4 rooms
          White       Blue        Gray
</code></pre>
<p>JavaScript classes work in a very similar way.</p>
<blockquote>
<p><strong>Class = Blueprint</strong> <strong>Object = Actual thing created from the blueprint</strong></p>
</blockquote>
<p>This single idea makes most of the beginner-level OOP syntax much easier to understand.</p>
<hr />
<h2>What Is a Class in JavaScript?</h2>
<p>A <strong>class</strong> is a blueprint for creating objects.</p>
<p>JavaScript provides the <code>class</code> keyword:</p>
<pre><code class="language-js">class Car {

}
</code></pre>
<p>We can define what every car should contain:</p>
<pre><code class="language-js">class Car {
  constructor(brand, model) {
    this.brand = brand;
    this.model = model;
  }

  drive() {
    console.log(`${this.brand} ${this.model} is driving.`);
  }
}
</code></pre>
<p>Think of this class as the blueprint:</p>
<pre><code class="language-text">                 Car CLASS
              ┌──────────────┐
              │ brand        │
              │ model        │
              │              │
              │ drive()      │
              └──────┬───────┘
                     │
              creates objects
                     │
          ┌──────────┼──────────┐
          ↓          ↓          ↓
        Car 1      Car 2      Car 3
       Toyota      Honda       BMW
       Corolla     Civic        X5
</code></pre>
<p>The class defines the <strong>structure and behavior</strong>.</p>
<p>The objects contain the actual values.</p>
<hr />
<h2>Creating Objects From a Class</h2>
<p>A class is only a blueprint. We still need to create objects from it.</p>
<p>JavaScript uses the <code>new</code> keyword:</p>
<pre><code class="language-js">const car1 = new Car("Toyota", "Corolla");
const car2 = new Car("Honda", "Civic");
const car3 = new Car("BMW", "X5");
</code></pre>
<p>Now we have three separate objects:</p>
<pre><code class="language-text">             Car Class
                │
               new
                │
     ┌──────────┼──────────┐
     ↓          ↓          ↓
   car1       car2       car3
 Toyota      Honda       BMW
 Corolla     Civic        X5
</code></pre>
<p>All three objects follow the same blueprint, but their data is different.</p>
<p>This is where <strong>code reusability</strong> becomes powerful.</p>
<p>Instead of designing the structure three times, we define it once and reuse it.</p>
<hr />
<h2>What Does the <code>new</code> Keyword Do?</h2>
<p>When you write:</p>
<pre><code class="language-js">const car = new Car("Toyota", "Corolla");
</code></pre>
<p>you're essentially saying:</p>
<blockquote>
<p>"Create a new object using the <code>Car</code> class."</p>
</blockquote>
<p>The basic flow is:</p>
<pre><code class="language-text">new Car(...)
     │
     ↓
Create a new object
     │
     ↓
Initialize its data
     │
     ↓
Return the object
</code></pre>
<p>That's why you'll commonly see:</p>
<pre><code class="language-js">const user = new User();
const product = new Product();
const student = new Student();
</code></pre>
<hr />
<h2>The Constructor Method</h2>
<p>Now let's understand this:</p>
<pre><code class="language-js">constructor(name, age) {
  this.name = name;
  this.age = age;
}
</code></pre>
<p>A <strong>constructor</strong> is a special method that runs automatically when we create a new object.</p>
<p>For example:</p>
<pre><code class="language-js">class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
</code></pre>
<p>When we write:</p>
<pre><code class="language-js">const person = new Person("Maaz", 20);
</code></pre>
<p>the constructor runs automatically.</p>
<p>Think of it like this:</p>
<pre><code class="language-text">new Person("Maaz", 20)
          │
          ↓
     constructor()
          │
          ├── name → "Maaz"
          └── age  → 20
          │
          ↓
      Person Object
</code></pre>
<p>The constructor's main job is usually to <strong>initialize the new object's properties</strong>.</p>
<hr />
<h2>Understanding <code>this</code></h2>
<p>You will see <code>this</code> everywhere in JavaScript classes.</p>
<p>Consider:</p>
<pre><code class="language-js">class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
</code></pre>
<p>Here:</p>
<pre><code class="language-js">this.name
</code></pre>
<p>means:</p>
<blockquote>
<p>"The <code>name</code> property of this particular object."</p>
</blockquote>
<p>For example:</p>
<pre><code class="language-js">const person1 = new Person("Maaz", 20);
const person2 = new Person("Ali", 21);
</code></pre>
<p>The result can be imagined as:</p>
<pre><code class="language-text">person1
┌──────────────┐
│ name: Maaz   │
│ age: 20      │
└──────────────┘

person2
┌──────────────┐
│ name: Ali    │
│ age: 21      │
└──────────────┘
</code></pre>
<p>When the constructor creates <code>person1</code>, <code>this</code> refers to <code>person1</code>.</p>
<p>When it creates <code>person2</code>, <code>this</code> refers to <code>person2</code>.</p>
<p>For now, remember:</p>
<blockquote>
<p><code>this</code> <strong>refers to the current object when working with an object instance.</strong></p>
</blockquote>
<hr />
<h2>Methods: Giving Objects Behavior</h2>
<p>Objects don't just store information. They can also perform actions.</p>
<p>These actions are called <strong>methods</strong>.</p>
<p>For example:</p>
<pre><code class="language-js">class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  introduce() {
    console.log(`Hi, I'm ${this.name}.`);
  }
}
</code></pre>
<p>Create an object:</p>
<pre><code class="language-js">const person = new Person("Maaz", 20);
</code></pre>
<p>Call its method:</p>
<pre><code class="language-js">person.introduce();
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Hi, I'm Maaz.
</code></pre>
<p>So now our object contains:</p>
<pre><code class="language-text">Person Object
├── name
├── age
└── introduce()
</code></pre>
<p>This is an important OOP idea:</p>
<blockquote>
<p><strong>Objects can contain both data and behavior.</strong></p>
</blockquote>
<hr />
<h2>A Practical Example: Student Class</h2>
<p>Let's build something you might actually use in an application.</p>
<p>Suppose we're creating a university system.</p>
<p>Every student has:</p>
<ul>
<li><p>name</p>
</li>
<li><p>age</p>
</li>
</ul>
<p>And every student should be able to display their details.</p>
<pre><code class="language-js">class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(`Name: ${this.name}, Age: ${this.age}`);
  }
}
</code></pre>
<p>Now create multiple students:</p>
<pre><code class="language-js">const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);
const student3 = new Student("Ahmed", 22);
</code></pre>
<p>And use them:</p>
<pre><code class="language-js">student1.displayDetails();
student2.displayDetails();
student3.displayDetails();
</code></pre>
<p>Output:</p>
<pre><code class="language-text">Name: Maaz, Age: 20
Name: Ali, Age: 21
Name: Ahmed, Age: 22
</code></pre>
<p>Look at what happened.</p>
<p>We wrote the structure <strong>once</strong>:</p>
<pre><code class="language-text">Student Class
     │
     ├── name
     ├── age
     └── displayDetails()
</code></pre>
<p>Then created many objects:</p>
<pre><code class="language-text">             Student Class
                  │
        ┌─────────┼─────────┐
        ↓         ↓         ↓
     student1  student2  student3
       Maaz       Ali      Ahmed
        20        21         22
</code></pre>
<p>That's <strong>reusability</strong> in action.</p>
<hr />
<h2>Basic Idea of Encapsulation</h2>
<p>Another important OOP concept is <strong>encapsulation</strong>.</p>
<p>Don't worry about the complicated definition.</p>
<p>At a beginner level, think of encapsulation as:</p>
<blockquote>
<p><strong>Keeping related data and the operations that work with that data together, while controlling how that data is changed.</strong></p>
</blockquote>
<p>Consider a bank account.</p>
<pre><code class="language-js">class BankAccount {
  constructor(balance) {
    this.balance = balance;
  }

  deposit(amount) {
    this.balance += amount;
  }

  withdraw(amount) {
    if (amount &gt; this.balance) {
      console.log("Insufficient balance.");
      return;
    }

    this.balance -= amount;
  }
}
</code></pre>
<p>Now:</p>
<pre><code class="language-js">const account = new BankAccount(1000);

account.deposit(500);
account.withdraw(200);
</code></pre>
<p>The account's data and related operations are grouped together:</p>
<pre><code class="language-text">             BankAccount
          ┌───────────────┐
          │ balance       │
          ├───────────────┤
          │ deposit()     │
          │ withdraw()    │
          └───────────────┘
</code></pre>
<p>This is the basic idea.</p>
<p>JavaScript has more advanced ways to implement encapsulation, such as private fields (<code>#</code>), getters, setters, and modules. Those can be learned later.</p>
<hr />
<h2>Class vs Object: Never Confuse These</h2>
<p>This is one of the most common beginner mistakes.</p>
<h3>Class</h3>
<p>A class is the <strong>blueprint</strong>.</p>
<pre><code class="language-js">class Student {
  // blueprint
}
</code></pre>
<h3>Object</h3>
<p>An object is an <strong>instance created from that blueprint</strong>.</p>
<pre><code class="language-js">const student = new Student();
</code></pre>
<p>Visualize it like this:</p>
<pre><code class="language-text">CLASS
(Blueprint)
   │
   │ new
   ↓
OBJECT
(Actual instance)
</code></pre>
<p>Or with multiple objects:</p>
<pre><code class="language-text">                 Student
                  CLASS
               (Blueprint)
                    │
             ┌──────┼──────┐
             ↓      ↓      ↓
          Object  Object  Object
          Maaz     Ali    Ahmed
</code></pre>
<p>Once this distinction is clear, classes become much less intimidating.</p>
<hr />
<h2>Why Use OOP?</h2>
<p>Imagine you're building a large application.</p>
<p>You might have:</p>
<pre><code class="language-text">Application
├── Users
├── Products
├── Orders
├── Payments
└── Notifications
</code></pre>
<p>Each entity has its own data and behavior.</p>
<p>For example:</p>
<pre><code class="language-text">User
├── name
├── email
├── login()
└── logout()

Product
├── name
├── price
└── updatePrice()

Order
├── items
├── total
└── calculateTotal()
</code></pre>
<p>OOP gives you a structured way to model these entities.</p>
<p>The biggest beginner-friendly benefits are:</p>
<ul>
<li><p><strong>Reusability</strong> — define a structure once and reuse it.</p>
</li>
<li><p><strong>Organization</strong> — keep related data and behavior together.</p>
</li>
<li><p><strong>Maintainability</strong> — larger codebases can become easier to manage.</p>
</li>
<li><p><strong>Modeling</strong> — real-world entities can be represented naturally.</p>
</li>
</ul>
<hr />
<h2>A Complete Example</h2>
<p>Here's everything together:</p>
<pre><code class="language-js">class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(
      `Student: ${this.name}, Age: ${this.age}`
    );
  }
}

const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);

student1.displayDetails();
student2.displayDetails();
</code></pre>
<p>The complete mental flow is:</p>
<pre><code class="language-text">class Student
      │
      │ defines
      ↓
properties + methods
      │
      │ new Student()
      ↓
┌───────────────┐
│ student1      │
│ name: Maaz    │
│ age: 20       │
└───────────────┘

┌───────────────┐
│ student2      │
│ name: Ali     │
│ age: 21       │
└───────────────┘
</code></pre>
<p>You define the blueprint once and create as many instances as your application needs.</p>
<hr />
<h2>Your Practice Challenge</h2>
<p>Now try building the <code>Student</code> class yourself.</p>
<h3>Requirements</h3>
<p>Create a class called <code>Student</code>.</p>
<p>It should have:</p>
<ul>
<li><p><code>name</code></p>
</li>
<li><p><code>age</code></p>
</li>
<li><p><code>displayDetails()</code> method</p>
</li>
</ul>
<p>Then create at least <strong>two student objects</strong>.</p>
<p>Your goal should be to reach something like:</p>
<pre><code class="language-text">Student Class
     │
     ├── name
     ├── age
     └── displayDetails()
            │
      ┌─────┴─────┐
      ↓           ↓
   Student 1   Student 2
     Maaz         Ali
      20          21
</code></pre>
<p>Try it before looking at the complete example above. Writing it yourself is where the concept really sticks.</p>
<hr />
<h2>The Key Idea</h2>
<p>If you're new to OOP, don't try to memorize everything at once.</p>
<p>Remember this:</p>
<pre><code class="language-text">CLASS
  ↓
Blueprint

new
  ↓
Creates an object

CONSTRUCTOR
  ↓
Initializes the object

PROPERTIES
  ↓
Store data

METHODS
  ↓
Define behavior

OBJECT
  ↓
Actual instance created from the class
</code></pre>
<p>Or, in one picture:</p>
<pre><code class="language-text">                 CLASS
              (Blueprint)
                   │
                  new
                   ↓
              ┌─────────┐
              │ OBJECT  │
              ├─────────┤
              │ Data    │
              │         │
              │ Methods │
              └─────────┘
</code></pre>
<p>That's the foundation of OOP in JavaScript.</p>
<hr />
<h2>The Core Insight</h2>
<p>Object-Oriented Programming isn't about memorizing complicated terminology.</p>
<p>At its core, it's about <strong>organizing related data and behavior into objects and creating reusable structures for those objects</strong>.</p>
<p>A JavaScript class gives you a blueprint:</p>
<pre><code class="language-js">class Student {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  displayDetails() {
    console.log(`${this.name} is ${this.age} years old.`);
  }
}
</code></pre>
<p>Then <code>new</code> creates actual objects from that blueprint:</p>
<pre><code class="language-js">const student1 = new Student("Maaz", 20);
const student2 = new Student("Ali", 21);
</code></pre>
<p>So whenever you see:</p>
<pre><code class="language-js">class → constructor → new → object → method
</code></pre>
<p>think:</p>
<pre><code class="language-text">Blueprint
   ↓
Build
   ↓
Object
   ↓
Data + Behavior
</code></pre>
<p>Once this becomes natural, concepts like <strong>inheritance, polymorphism, abstraction, private fields, getters, and setters</strong> become much easier to learn.</p>
<p>The goal isn't to write more classes.</p>
<p>The goal is to use the right structure to make your JavaScript applications <strong>clearer, more reusable, and easier to maintain</strong>.</p>
<hr />
<h2>Bonus: What Are JavaScript Classes Really?</h2>
<h3>JavaScript Classes vs. C++/Java Classes</h3>
<p>If you've worked with <strong>C++ or Java</strong>, there's an important difference to understand.</p>
<p>When you write:</p>
<pre><code class="language-js">class Student {
  constructor(name) {
    this.name = name;
  }
}
</code></pre>
<p>JavaScript's <code>class</code> syntax may look very similar to a class in Java or C++.</p>
<p>But <strong>JavaScript's object model works differently</strong>.</p>
<p>Java and C++ are traditionally <strong>class-based languages</strong>. Classes are a fundamental part of how objects and inheritance are structured.</p>
<p>JavaScript, however, is fundamentally <strong>prototype-based</strong>.</p>
<pre><code class="language-text">Java / C++
     │
     ↓
   CLASS
     │
     ↓
  OBJECTS


JavaScript
     │
     ↓
 PROTOTYPE SYSTEM
     │
     ↓
 class syntax
 (cleaner interface)
     │
     ↓
  OBJECTS
</code></pre>
<p>So don't assume:</p>
<blockquote>
<p><code>class</code> in JavaScript = exactly the same kind of class as in Java or C++.</p>
</blockquote>
<p>The syntax looks familiar because JavaScript's <code>class</code> syntax was designed to provide a more familiar and cleaner way to work with objects and inheritance.</p>
<p>Underneath, JavaScript still uses <strong>prototypes</strong>.</p>
<h3>Why Does This Matter?</h3>
<p>For everyday beginner-level JavaScript, you can comfortably write:</p>
<pre><code class="language-js">class Student {
  constructor(name) {
    this.name = name;
  }

  introduce() {
    console.log(`Hi, I'm ${this.name}`);
  }
}
</code></pre>
<p>You don't need to think about prototypes every time you create a class.</p>
<p>But as you progress into topics such as:</p>
<ul>
<li><p>inheritance</p>
</li>
<li><p><code>extends</code></p>
</li>
<li><p><code>super</code></p>
</li>
<li><p>prototypes</p>
</li>
<li><p>method lookup</p>
</li>
<li><p><code>Object.getPrototypeOf()</code></p>
</li>
</ul>
<p>understanding this distinction becomes very useful.</p>
<p>So remember this simple rule:</p>
<blockquote>
<p><strong>JavaScript looks class-based on the surface, but its object model is prototype-based underneath.</strong></p>
</blockquote>
<p>That is one of the most important differences between JavaScript's <code>class</code> syntax and the traditional class model you'll encounter in languages such as Java and C++.</p>
]]></content:encoded></item><item><title><![CDATA[How a Browser Works: From URL to Pixels on Your Screen]]></title><description><![CDATA[What happens after you type a URL into your browser and press Enter?
A webpage may appear in a second, but a lot happens behind the scenes.
The browser has to find the server, download files, understa]]></description><link>https://maazzz.hashnode.dev/how-a-browser-works-from-url-to-pixels-on-your-screen</link><guid isPermaLink="true">https://maazzz.hashnode.dev/how-a-browser-works-from-url-to-pixels-on-your-screen</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Fri, 21 Aug 2026 16:31:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/292585fe-ac3e-4273-899a-10270ce7d0d4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>What happens after you type a URL into your browser and press <strong>Enter</strong>?</p>
<p>A webpage may appear in a second, but a lot happens behind the scenes.</p>
<p>The browser has to find the server, download files, understand HTML and CSS, run JavaScript, calculate where everything belongs, and finally turn all of that information into <strong>pixels on your screen</strong>.</p>
<p>So a browser is much more than an application that "opens websites."</p>
<p>It is a collection of components that work together to turn web code into an interactive visual experience.</p>
<h2>What Is a Browser?</h2>
<p>A <strong>web browser</strong> is software that retrieves resources from the web and processes them so you can interact with websites.</p>
<p>Those resources can include:</p>
<ul>
<li><p>HTML</p>
</li>
<li><p>CSS</p>
</li>
<li><p>JavaScript</p>
</li>
<li><p>Images</p>
</li>
<li><p>Fonts</p>
</li>
<li><p>Videos</p>
</li>
<li><p>Other network resources</p>
</li>
</ul>
<p>Popular browsers include Chrome, Firefox, Safari, and Edge.</p>
<p>Although their internal implementations differ, the basic process is similar:</p>
<pre><code class="language-text">URL
 ↓
Network Request
 ↓
HTML + CSS + JavaScript
 ↓
Parse
 ↓
DOM + CSSOM
 ↓
Render Tree
 ↓
Layout
 ↓
Paint
 ↓
Pixels on Screen
</code></pre>
<p>Let's break this journey down.</p>
<h2>Main Parts of a Browser</h2>
<p>A browser contains several major components.</p>
<pre><code class="language-text">              Browser
                 |
     ┌───────────┼───────────┐
     ↓           ↓           ↓
    UI        Browser     Networking
              Engine          |
                 |             ↓
                 |        Web Resources
                 ↓
          Rendering Engine
                 |
          JavaScript Engine
</code></pre>
<p>The exact architecture differs between browsers, but the responsibilities can be understood separately.</p>
<h3>User Interface</h3>
<p>This is the part you interact with directly:</p>
<ul>
<li><p>Address bar</p>
</li>
<li><p>Tabs</p>
</li>
<li><p>Back and forward buttons</p>
</li>
<li><p>Bookmarks</p>
</li>
<li><p>Menus</p>
</li>
</ul>
<p>The UI is basically the <strong>control panel</strong> of the browser.</p>
<p>But it is not responsible for turning HTML into a webpage.</p>
<h3>Browser Engine vs Rendering Engine</h3>
<p>These terms can sound confusing.</p>
<p>The <strong>browser engine</strong> coordinates different browser operations and connects the user interface with the underlying browser components.</p>
<p>The <strong>rendering engine</strong> is responsible for taking web content such as HTML and CSS and turning it into something that can be displayed.</p>
<p>Different browsers use different implementations. For example, Chromium-based browsers use <strong>Blink</strong>, while Firefox uses <strong>Gecko</strong>.</p>
<p>You don't need to memorize the engine names yet. The important idea is:</p>
<blockquote>
<p><strong>The rendering engine turns web documents into what you see on the screen.</strong></p>
</blockquote>
<h2>Step 1: The Browser Fetches the Website</h2>
<p>When you enter:</p>
<pre><code class="language-text">https://example.com
</code></pre>
<p>the browser first needs to communicate with the server.</p>
<p>It performs network operations such as <strong>DNS resolution</strong> to find the server's IP address and then establishes the required network connection.</p>
<p>The browser sends an HTTP request asking for the resource.</p>
<p>The server may respond with HTML:</p>
<pre><code class="language-text">Browser
   ↓ HTTP Request
Server
   ↓ HTML Response
Browser
</code></pre>
<p>But HTML is only the beginning.</p>
<p>The HTML may reference CSS, JavaScript, images, fonts, and other resources, which the browser may need to request as well.</p>
<h2>Step 2: HTML Becomes the DOM</h2>
<p>The browser receives HTML, but it cannot simply display the raw text.</p>
<p>It needs to understand the structure.</p>
<p>This is called <strong>parsing</strong>.</p>
<p>Consider:</p>
<pre><code class="language-html">&lt;body&gt;
  &lt;h1&gt;Hello&lt;/h1&gt;
  &lt;p&gt;Welcome!&lt;/p&gt;
&lt;/body&gt;
</code></pre>
<p>The browser parses this document and builds a structure called the <strong>DOM (Document Object Model)</strong>.</p>
<p>You can think of the DOM as a <strong>tree</strong>:</p>
<pre><code class="language-text">Document
   |
   └── body
       ├── h1
       │   └── "Hello"
       |
       └── p
           └── "Welcome!"
</code></pre>
<p>Each HTML element becomes part of this tree.</p>
<p>JavaScript can later interact with this structure to change the webpage.</p>
<h2>What Does "Parsing" Mean?</h2>
<p>Parsing simply means:</p>
<blockquote>
<p><strong>Taking something written in a particular format and turning it into a structure the computer can understand.</strong></p>
</blockquote>
<p>For example, imagine:</p>
<pre><code class="language-text">2 + 3 × 4
</code></pre>
<p>A computer needs to understand that this is not just a sequence of characters.</p>
<p>It can build a structure representing the expression:</p>
<pre><code class="language-text">       +
      / \
     2   ×
        / \
       3   4
</code></pre>
<p>The browser does something similar with HTML.</p>
<p>It takes text and turns it into a meaningful structure.</p>
<h2>Step 3: CSS Becomes the CSSOM</h2>
<p>HTML tells the browser <strong>what elements exist</strong>.</p>
<p>CSS tells it <strong>how those elements should look</strong>.</p>
<p>For example:</p>
<pre><code class="language-css">h1 {
  font-size: 32px;
}
</code></pre>
<p>The browser parses the CSS and creates another structure called the <strong>CSSOM (CSS Object Model)</strong>.</p>
<p>You can think of it as a representation of the styling rules the browser needs to apply.</p>
<p>So we have:</p>
<pre><code class="language-text">HTML
 ↓
DOM

CSS
 ↓
CSSOM
</code></pre>
<h2>Step 4: DOM + CSSOM → Render Tree</h2>
<p>Now the browser has two important pieces of information:</p>
<p><strong>DOM:</strong> What exists?</p>
<p><strong>CSSOM:</strong> How should it look?</p>
<p>The browser combines the relevant information to create a <strong>render tree</strong>.</p>
<pre><code class="language-text">HTML → DOM ─────┐
                ├──→ Render Tree
CSS  → CSSOM ───┘
</code></pre>
<p>The render tree contains the information needed to determine what should actually be displayed.</p>
<p>Not every DOM node necessarily appears in the render tree. For example, an element hidden with <code>display: none</code> does not need to be rendered.</p>
<h2>Step 5: Layout</h2>
<p>Now the browser needs to calculate the exact position and size of visible elements.</p>
<p>This process is called <strong>layout</strong>, often referred to as <strong>reflow</strong> when layout is recalculated.</p>
<p>The browser determines things such as:</p>
<ul>
<li><p>Width</p>
</li>
<li><p>Height</p>
</li>
<li><p>Position</p>
</li>
<li><p>Spacing</p>
</li>
<li><p>Relationships between elements</p>
</li>
</ul>
<p>For example:</p>
<pre><code class="language-text">Where should the heading go?
How wide should this paragraph be?
Where should the image appear?
</code></pre>
<p>The browser calculates the answers based on the document and styling.</p>
<h2>Step 6: Painting</h2>
<p>After the browser knows where everything belongs, it needs to draw it.</p>
<p>This stage is called <strong>painting</strong>.</p>
<p>The browser determines things such as:</p>
<ul>
<li><p>Text</p>
</li>
<li><p>Colors</p>
</li>
<li><p>Borders</p>
</li>
<li><p>Backgrounds</p>
</li>
<li><p>Images</p>
</li>
<li><p>Shadows</p>
</li>
</ul>
<p>The result is eventually displayed as pixels on your screen.</p>
<pre><code class="language-text">DOM + CSSOM
     ↓
Render Tree
     ↓
Layout
     ↓
Paint
     ↓
Pixels
</code></pre>
<h2>The Complete Journey</h2>
<p>Putting everything together:</p>
<pre><code class="language-text">You enter a URL
       ↓
DNS + Network
       ↓
HTTP Request
       ↓
HTML Response
       ↓
HTML Parsing
       ↓
DOM
       +
CSS Parsing
       ↓
CSSOM
       ↓
Render Tree
       ↓
Layout
       ↓
Paint
       ↓
Pixels on Screen
</code></pre>
<p>JavaScript can also run during this process and modify the DOM or styles, which may cause parts of the page to be recalculated and painted again.</p>
<h2>Final Mental Model</h2>
<p>You don't need to memorize every browser component.</p>
<p>Just remember the story:</p>
<blockquote>
<p><strong>The browser fetches resources, understands HTML and CSS, builds structures from them, calculates how the page should look, and finally paints those results as pixels on your screen.</strong></p>
</blockquote>
<p>The next time you press Enter after typing a URL, remember that the browser isn't simply "opening a website."</p>
<p>It is taking <strong>network data and turning it into an interactive visual experience</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Network Devices: Modem, Router, Switch, Firewall & Load Balancer]]></title><description><![CDATA[When you open a website, your request may travel through many systems before reaching the server.
Even in a simple home network, several devices can have different responsibilities:
Internet
   ↓
Mode]]></description><link>https://maazzz.hashnode.dev/network-devices-modem-router-switch-firewall-load-balancer</link><guid isPermaLink="true">https://maazzz.hashnode.dev/network-devices-modem-router-switch-firewall-load-balancer</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Fri, 21 Aug 2026 16:25:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/4be9c7df-9960-4ebb-ad31-1853e01a1322.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you open a website, your request may travel through many systems before reaching the server.</p>
<p>Even in a simple home network, several devices can have different responsibilities:</p>
<pre><code class="language-text">Internet
   ↓
Modem
   ↓
Router
   ↓
Switch
   ↓
Your Devices
</code></pre>
<p>In larger networks, <strong>firewalls</strong> and <strong>load balancers</strong> can also become important.</p>
<p>Understanding these devices gives you a better picture of how networks work and what happens behind the scenes when your application communicates with another computer.</p>
<h2>1. What Is a Modem?</h2>
<p>A <strong>modem</strong> connects your local network to your Internet Service Provider (ISP).</p>
<p>The word modem comes from <strong>modulator-demodulator</strong>. Traditionally, its job was to convert signals between the format used by the ISP's connection and the digital data your network devices understand.</p>
<p>Think of the modem as the <strong>bridge between your network and your ISP</strong>.</p>
<pre><code class="language-text">Your Network
     ↓
   Modem
     ↓
    ISP
     ↓
 Internet
</code></pre>
<p>A modem does not primarily decide where traffic should go inside your home network. That is mainly the router's job.</p>
<p>Modern devices often combine a modem and router into a single box, which is why the distinction can sometimes be confusing.</p>
<h2>2. What Is a Router?</h2>
<p>A <strong>router</strong> connects different networks and decides where network traffic should go.</p>
<p>In a home network, your router connects your local devices to the internet.</p>
<p>For example:</p>
<pre><code class="language-text">Laptop ──┐
Phone  ──┼── Router ── Internet
TV     ──┘
</code></pre>
<p>The router looks at destination information in network packets and forwards traffic toward the appropriate network.</p>
<p>Think of it as <strong>traffic control</strong>.</p>
<p>It helps answer:</p>
<blockquote>
<p>"Where should this traffic go next?"</p>
</blockquote>
<p>A home router commonly also provides services such as <strong>NAT, DHCP, and Wi-Fi</strong>, although these are separate functions from routing itself.</p>
<h2>3. Switch vs Hub</h2>
<p>Inside a local network, devices may connect through a <strong>switch</strong>.</p>
<p>A switch forwards Ethernet frames between devices on a local network. It learns which devices are reachable through which ports by observing <strong>MAC addresses</strong>.</p>
<p>For example:</p>
<pre><code class="language-text">PC ──┐
     │
Laptop ── Switch ── Server
     │
Printer ─┘
</code></pre>
<p>A switch tries to send traffic only toward the port where the destination device is located.</p>
<h3>What About a Hub?</h3>
<p>A <strong>hub</strong> is much simpler.</p>
<p>When a hub receives a signal, it essentially broadcasts it out to all connected ports.</p>
<pre><code class="language-text">        Hub
     /  |  |  \
   PC  TV  PC Printer
</code></pre>
<p>A switch is more selective:</p>
<pre><code class="language-text">        Switch
     /  |  |  \
   PC  TV  PC Printer
       ↑
  Only the needed
  destination
</code></pre>
<p>This is why switches are much more useful than traditional hubs in modern Ethernet networks.</p>
<p>A simple way to remember:</p>
<blockquote>
<p><strong>Hub: send everywhere.</strong></p>
</blockquote>
<blockquote>
<p><strong>Switch: send where needed.</strong></p>
</blockquote>
<h2>4. What Is a Firewall?</h2>
<p>A <strong>firewall</strong> controls network traffic based on defined security rules.</p>
<p>It can inspect traffic and decide whether it should be <strong>allowed or blocked</strong>.</p>
<p>Think of it as a <strong>security gate</strong>.</p>
<pre><code class="language-text">Internet
   ↓
Firewall
   ↓
Internal Network
</code></pre>
<p>For example, a firewall might allow web traffic to a public server while blocking unauthorized connections to internal systems.</p>
<p>Firewalls can exist in different places, including network appliances, routers, operating systems, and cloud environments.</p>
<p>For software engineers, the important idea is that a firewall can control <strong>which network connections are allowed to reach your application</strong>.</p>
<h2>5. What Is a Load Balancer?</h2>
<p>Now imagine your application becomes popular.</p>
<p>One server may no longer be enough to handle all incoming requests.</p>
<p>Instead, you can run multiple servers:</p>
<pre><code class="language-text">             Server 1
           /
Users → Load Balancer → Server 2
           \
             Server 3
</code></pre>
<p>A <strong>load balancer</strong> receives incoming traffic and distributes it across multiple backend servers.</p>
<p>For example, if three servers are available, the load balancer can send different requests to different servers.</p>
<p>This provides several benefits:</p>
<ul>
<li><p>Better scalability</p>
</li>
<li><p>Improved availability</p>
</li>
<li><p>Traffic distribution</p>
</li>
<li><p>Health checking</p>
</li>
<li><p>Easier server maintenance</p>
</li>
</ul>
<p>Think of it like a <strong>toll booth system</strong>.</p>
<p>Instead of sending every car through one lane, traffic is distributed across multiple lanes.</p>
<p>If one backend server becomes unhealthy, a load balancer can often stop sending new traffic to it.</p>
<h2>How Do These Devices Work Together?</h2>
<p>Consider a simple web application deployed in production:</p>
<pre><code class="language-text">                    Internet
                       ↓
                    Firewall
                       ↓
                 Load Balancer
                  /     |     \
                 ↓      ↓      ↓
             Server 1 Server 2 Server 3
                       ↓
                    Database
</code></pre>
<p>For a home or small office network, the architecture may look different:</p>
<pre><code class="language-text">Internet
   ↓
Modem
   ↓
Router
   ↓
Switch
   ├── Laptop
   ├── Desktop
   ├── Printer
   └── Access Point
</code></pre>
<p>In some networks, one physical device may perform several of these roles. For example, a home gateway may combine a <strong>modem, router, switch, firewall, and Wi-Fi access point</strong> into one device.</p>
<p>The functions are still conceptually different even when the hardware is combined.</p>
<h2>How This Connects to Software Engineering</h2>
<p>As a developer, you may not configure physical network hardware every day, but these concepts appear constantly in backend and cloud architecture.</p>
<p>A production application might look like:</p>
<pre><code class="language-text">Client
  ↓
Firewall
  ↓
Load Balancer
  ↓
Backend Servers
  ↓
Database
</code></pre>
<p>When you deploy an API, scale your application, configure security rules, or troubleshoot why a server cannot be reached, understanding these components becomes extremely useful.</p>
<p>You can think of their responsibilities like this:</p>
<table>
<thead>
<tr>
<th>Device</th>
<th>Main Responsibility</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Modem</strong></td>
<td>Connects your network to the ISP</td>
</tr>
<tr>
<td><strong>Router</strong></td>
<td>Directs traffic between networks</td>
</tr>
<tr>
<td><strong>Switch</strong></td>
<td>Connects devices within a local network</td>
</tr>
<tr>
<td><strong>Hub</strong></td>
<td>Broadcasts traffic to connected devices</td>
</tr>
<tr>
<td><strong>Firewall</strong></td>
<td>Allows or blocks traffic based on security rules</td>
</tr>
<tr>
<td><strong>Load Balancer</strong></td>
<td>Distributes traffic across servers</td>
</tr>
</tbody></table>
<p>The key is not to memorize the devices individually.</p>
<p>Understand the journey:</p>
<blockquote>
<p><strong>The modem connects you to the ISP, the router moves traffic between networks, the switch connects local devices, the firewall controls access, and the load balancer distributes application traffic across servers.</strong></p>
</blockquote>
<p>Together, these components form the foundation of many networks — from a small home setup to large production systems running applications for millions of users.</p>
]]></content:encoded></item><item><title><![CDATA[cURL Explained: How to Talk to Servers from the Terminal]]></title><description><![CDATA[When you build websites or applications, your program often needs to talk to a server.
A server is simply a computer or system that receives requests, processes them, and sends responses back.
For exa]]></description><link>https://maazzz.hashnode.dev/curl-explained-how-to-talk-to-servers-from-the-terminal</link><guid isPermaLink="true">https://maazzz.hashnode.dev/curl-explained-how-to-talk-to-servers-from-the-terminal</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Thu, 20 Aug 2026 19:37:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/0e796dd7-b194-43d6-a8a3-a06964b6150c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you build websites or applications, your program often needs to <strong>talk to a server</strong>.</p>
<p>A server is simply a computer or system that receives requests, processes them, and sends responses back.</p>
<p>For example, when you open a website, your browser sends a request to a server. The server processes that request and returns data such as HTML, JSON, images, or other resources.</p>
<p>But what if you want to make that request <strong>without opening a browser</strong>?</p>
<p>That's where <strong>cURL</strong> comes in.</p>
<h2>What Is cURL?</h2>
<p><strong>cURL</strong> is a command-line tool used to transfer data between your computer and a server.</p>
<p>In simple terms:</p>
<blockquote>
<p><strong>cURL lets you send messages to servers directly from your terminal.</strong></p>
</blockquote>
<p>You can use it to communicate with websites, REST APIs, backend applications, and many other services.</p>
<p>A basic flow looks like this:</p>
<pre><code class="language-text">Your Terminal
     |
     | cURL Request
     ↓
   Server
     |
     | Response
     ↓
Your Terminal
</code></pre>
<p>cURL supports many protocols, but it is especially useful when working with <strong>HTTP and HTTPS</strong>.</p>
<h2>Why Do Programmers Use cURL?</h2>
<p>You might wonder:</p>
<blockquote>
<p>"If I already have a browser, why do I need cURL?"</p>
</blockquote>
<p>Because cURL gives developers direct control over requests and is extremely useful for testing and debugging.</p>
<p>For example, you can use cURL to:</p>
<ul>
<li><p>Test whether a server is responding</p>
</li>
<li><p>Test REST APIs</p>
</li>
<li><p>Send GET and POST requests</p>
</li>
<li><p>Check HTTP status codes</p>
</li>
<li><p>Debug backend applications</p>
</li>
<li><p>Test authentication and API endpoints</p>
</li>
<li><p>Automate requests from scripts</p>
</li>
</ul>
<p>This makes cURL especially useful for <strong>backend and API development</strong>.</p>
<h2>Your First cURL Request</h2>
<p>Let's start with the simplest possible example:</p>
<pre><code class="language-bash">curl https://example.com
</code></pre>
<p>This tells cURL:</p>
<blockquote>
<p>"Send a request to <code>example.com</code> and show me the response."</p>
</blockquote>
<p>The server receives the request and sends something back.</p>
<p>You may see HTML similar to:</p>
<pre><code class="language-html">&lt;h1&gt;Example Domain&lt;/h1&gt;
&lt;p&gt;This domain is for use in illustrative examples.&lt;/p&gt;
</code></pre>
<p>Your browser normally receives this HTML and turns it into a visual webpage.</p>
<p>cURL simply shows you the response directly in the terminal.</p>
<h2>What Is a Request and Response?</h2>
<p>Most communication between a client and an HTTP server follows a simple pattern:</p>
<pre><code class="language-text">Client
  |
  | HTTP Request
  ↓
Server
  |
  | HTTP Response
  ↓
Client
</code></pre>
<p>The <strong>request</strong> tells the server what you want.</p>
<p>The <strong>response</strong> tells you what happened.</p>
<p>A response contains important information such as a <strong>status code</strong> and the data returned by the server.</p>
<p>For example:</p>
<pre><code class="language-text">HTTP/1.1 200 OK
</code></pre>
<p>The <code>200</code> status code means the request was successful.</p>
<p>Other common status codes include:</p>
<ul>
<li><p><code>200</code> - Successful</p>
</li>
<li><p><code>404</code> - Resource not found</p>
</li>
<li><p><code>401</code> - Authentication required</p>
</li>
<li><p><code>500</code> - Server-side error</p>
</li>
</ul>
<p>You can ask cURL to show response details using:</p>
<pre><code class="language-bash">curl -i https://example.com
</code></pre>
<p>The <code>-i</code> option includes the response headers along with the response body.</p>
<h2>Using cURL with APIs</h2>
<p>This is where cURL becomes particularly useful for developers.</p>
<p>Suppose you have an API endpoint:</p>
<pre><code class="language-text">https://api.example.com/users
</code></pre>
<p>A simple <strong>GET</strong> request asks the server to retrieve data:</p>
<pre><code class="language-bash">curl https://api.example.com/users
</code></pre>
<p>The server might respond with JSON:</p>
<pre><code class="language-json">[
  {
    "id": 1,
    "name": "Maaz"
  }
]
</code></pre>
<p>Now suppose you want to create a new user.</p>
<p>You can use a <strong>POST</strong> request:</p>
<pre><code class="language-bash">curl -X POST https://api.example.com/users
</code></pre>
<p><code>GET</code> and <code>POST</code> are HTTP methods.</p>
<p>Think of them simply as:</p>
<blockquote>
<p><strong>GET = "Give me something."</strong></p>
</blockquote>
<blockquote>
<p><strong>POST = "Here is some data; create or process it."</strong></p>
</blockquote>
<p>In real APIs, POST requests usually include additional data and headers. For example:</p>
<pre><code class="language-bash">curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Maaz"}'
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>-X POST</code> specifies the HTTP method.</p>
</li>
<li><p><code>-H</code> adds an HTTP header.</p>
</li>
<li><p><code>-d</code> sends data in the request body.</p>
</li>
</ul>
<p>You don't need to memorize these options immediately. The important thing is understanding what the request is doing.</p>
<h2>Browser vs cURL</h2>
<p>A browser and cURL can both communicate with the same server.</p>
<p>The difference is mainly how you interact with the response.</p>
<pre><code class="language-text">Browser
   |
   | HTTP Request
   ↓
Server
   |
   | HTML / JSON / Data
   ↓
Browser → Displays the result

cURL
   |
   | HTTP Request
   ↓
Server
   |
   | HTML / JSON / Data
   ↓
Terminal → Shows the result
</code></pre>
<p>A browser is designed to give users a visual experience.</p>
<p>cURL is designed to give developers <strong>direct command-line access to network communication</strong>.</p>
<h2>Common Beginner Mistakes</h2>
<h3>1. Forgetting the URL</h3>
<pre><code class="language-bash">curl
</code></pre>
<p>cURL needs a destination. Start with:</p>
<pre><code class="language-bash">curl https://example.com
</code></pre>
<h3>2. Confusing GET and POST</h3>
<p>A GET request normally retrieves data, while POST is commonly used to send data to a server.</p>
<p>Don't choose a method based only on what looks shorter. Follow the API's documentation.</p>
<h3>3. Thinking cURL Is an API</h3>
<p>cURL is <strong>not an API</strong>.</p>
<p>It is a tool that can communicate with APIs.</p>
<p>Think of it this way:</p>
<blockquote>
<p><strong>API = the service you communicate with.</strong></p>
</blockquote>
<blockquote>
<p><strong>cURL = one tool you can use to communicate with it.</strong></p>
</blockquote>
<h3>4. Expecting Every Response to Be HTML</h3>
<p>APIs commonly return <strong>JSON</strong>, while websites may return HTML.</p>
<p>The response depends on what the server provides.</p>
<h2>cURL in Backend Development</h2>
<p>cURL is a small tool, but it teaches an important concept:</p>
<pre><code class="language-text">Request → Server → Response
</code></pre>
<p>That same basic idea appears throughout web development.</p>
<p>When you build a backend API, other applications need to send requests to it. cURL lets you test those endpoints directly without building a frontend first.</p>
<p>For example:</p>
<pre><code class="language-text">cURL
  ↓
POST /users
  ↓
Your Backend API
  ↓
Database
  ↓
JSON Response
  ↓
cURL
</code></pre>
<h2>Final Takeaway</h2>
<p>cURL is a command-line tool that lets you <strong>communicate with servers directly from your terminal</strong>.</p>
<p>Start with:</p>
<pre><code class="language-bash">curl https://example.com
</code></pre>
<p>Then learn how requests and responses work, followed by GET and POST requests for APIs.</p>
<p>You don't need to memorize dozens of cURL options.</p>
<p>First understand the core idea:</p>
<blockquote>
<p><strong>cURL sends a request. The server processes it. The server sends a response. cURL shows you what came back.</strong></p>
</blockquote>
<p>Once this becomes familiar, testing websites, REST APIs, and your own backend services becomes much easier.</p>
]]></content:encoded></item><item><title><![CDATA[DNS Records Explained: A, AAAA, CNAME, MX, TXT & NS]]></title><description><![CDATA[How does your browser know where a website lives?
You type:
example.com

But your computer cannot directly connect to a name like example.com. It needs an IP address.
This is where DNS (Domain Name Sy]]></description><link>https://maazzz.hashnode.dev/dns-records-explained-a-aaaa-cname-mx-txt-ns</link><guid isPermaLink="true">https://maazzz.hashnode.dev/dns-records-explained-a-aaaa-cname-mx-txt-ns</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Wed, 12 Aug 2026 17:35:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/0aaf286a-c8ef-4cc7-8c4e-1a6734e0a099.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>How does your browser know where a website lives?</p>
<p>You type:</p>
<pre><code class="language-text">example.com
</code></pre>
<p>But your computer cannot directly connect to a name like <code>example.com</code>. It needs an <strong>IP address</strong>.</p>
<p>This is where <strong>DNS (Domain Name System)</strong> comes in.</p>
<p>Think of DNS as the <strong>phonebook of the internet</strong>. You know someone's name, but the phonebook helps you find their phone number. DNS does something similar: you know a domain name, and DNS helps your device find the information it needs.</p>
<p>But DNS does not store just one type of information.</p>
<p>It uses different <strong>DNS records</strong>, and each record has a specific job.</p>
<p>Let's understand them one by one.</p>
<h2>What Are DNS Records?</h2>
<p>A DNS record is simply a piece of information stored in the DNS system for a domain.</p>
<p>For example:</p>
<pre><code class="language-text">example.com → 192.0.2.10
</code></pre>
<p>This tells us that <code>example.com</code> can be reached at a particular IP address.</p>
<p>But a domain also needs information about its name servers, email servers, aliases, and verification details.</p>
<p>That's why different types of DNS records exist.</p>
<hr />
<h2>1. NS Record — Who Manages the Domain?</h2>
<p><strong>NS (Name Server) records</strong> tell us which DNS servers are responsible for a domain.</p>
<p>Think of it like asking:</p>
<blockquote>
<p>"Which office keeps the official information for this domain?"</p>
</blockquote>
<p>For example:</p>
<pre><code class="language-text">example.com → ns1.example-dns.com
example.com → ns2.example-dns.com
</code></pre>
<p>These name servers are responsible for answering DNS questions about <code>example.com</code>.</p>
<p>So remember:</p>
<blockquote>
<p><strong>NS records tell us who is responsible for the DNS information.</strong></p>
</blockquote>
<p>They do <strong>not</strong> directly tell your browser which web server to connect to.</p>
<hr />
<h2>2. A Record — Domain to IPv4 Address</h2>
<p>An <strong>A record</strong> connects a domain name to an <strong>IPv4 address</strong>.</p>
<p>For example:</p>
<pre><code class="language-text">example.com → 192.0.2.10
</code></pre>
<p>When your browser needs to find the IPv4 address of a website, it can use the domain's A record.</p>
<p>Think of it as:</p>
<blockquote>
<p><strong>Name → House address</strong></p>
</blockquote>
<p>The domain is the name, and the IPv4 address is where the server lives.</p>
<hr />
<h2>3. AAAA Record — Domain to IPv6 Address</h2>
<p>An <strong>AAAA record</strong> does a similar job to an A record, but for <strong>IPv6</strong>.</p>
<p>For example:</p>
<pre><code class="language-text">example.com → 2001:db8::10
</code></pre>
<p>So the difference is simple:</p>
<table>
<thead>
<tr>
<th>Record</th>
<th>Points to</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>IPv4 address</td>
</tr>
<tr>
<td>AAAA</td>
<td>IPv6 address</td>
</tr>
</tbody></table>
<p>If A is the address written in the older IPv4 format, AAAA is the address using the newer IPv6 format.</p>
<hr />
<h2>4. CNAME Record — One Name to Another Name</h2>
<p>A <strong>CNAME (Canonical Name)</strong> record points one domain name to <strong>another domain name</strong>.</p>
<p>For example:</p>
<pre><code class="language-text">www.example.com → example.com
</code></pre>
<p>This means:</p>
<blockquote>
<p>"For <code>www.example.com</code>, use <code>example.com</code> as the canonical name."</p>
</blockquote>
<p>Notice that CNAME points to <strong>another name</strong>, not directly to an IP address.</p>
<p>This is an important difference:</p>
<pre><code class="language-text">A Record:
example.com → 192.0.2.10

CNAME:
www.example.com → example.com
</code></pre>
<p>A CNAME is useful when multiple names should ultimately use the same destination without manually maintaining multiple IP addresses.</p>
<hr />
<h2>5. MX Record — Where Should Email Go?</h2>
<p>A website domain can also be used for email.</p>
<p>For example:</p>
<pre><code class="language-text">hello@example.com
</code></pre>
<p>But how does the internet know which server should receive that email?</p>
<p>That's the job of an <strong>MX (Mail Exchange) record</strong>.</p>
<p>An MX record tells mail servers:</p>
<blockquote>
<p>"For email sent to <code>example.com</code>, deliver it to this mail server."</p>
</blockquote>
<p>For example:</p>
<pre><code class="language-text">example.com → mail.example.com
</code></pre>
<p>MX records can also have a <strong>priority value</strong>, which helps determine which mail server should be preferred when multiple servers exist.</p>
<p>So remember:</p>
<blockquote>
<p><strong>A/AAAA records help find web servers; MX records help find mail servers.</strong></p>
</blockquote>
<hr />
<h2>6. TXT Record — Extra Information</h2>
<p>A <strong>TXT (Text)</strong> record stores text information associated with a domain.</p>
<p>It is commonly used for <strong>verification and security-related purposes</strong>.</p>
<p>For example, a service may ask you to add a TXT record to prove:</p>
<blockquote>
<p>"You control this domain."</p>
</blockquote>
<p>TXT records are also commonly used for email security technologies such as <strong>SPF, DKIM, and DMARC</strong>.</p>
<p>A simple example might look like:</p>
<pre><code class="language-text">example.com → "verification=abc123"
</code></pre>
<p>So you can think of TXT records as:</p>
<blockquote>
<p><strong>Extra information that other services can read.</strong></p>
</blockquote>
<hr />
<h2>How Do All These Records Work Together?</h2>
<p>A single website can have many DNS records, each solving a different problem.</p>
<p>Imagine we have:</p>
<pre><code class="language-text">example.com
</code></pre>
<p>Its DNS setup could look like this:</p>
<pre><code class="language-text">NS
example.com
   ↓
ns1.dns-provider.com

A
example.com
   ↓
192.0.2.10

AAAA
example.com
   ↓
2001:db8::10

CNAME
www.example.com
   ↓
example.com

MX
example.com
   ↓
mail.example.com

TXT
example.com
   ↓
"verification=abc123"
</code></pre>
<p>Each record answers a different question.</p>
<h3>When Someone Visits the Website</h3>
<p>The browser needs an IP address, so DNS can return an <strong>A or AAAA record</strong>.</p>
<pre><code class="language-text">Browser
   ↓
example.com
   ↓
DNS
   ↓
A / AAAA Record
   ↓
IP Address
   ↓
Web Server
</code></pre>
<h3>When Someone Sends an Email</h3>
<p>The email system needs to know where the domain's mail should go.</p>
<pre><code class="language-text">Sender
   ↓
hello@example.com
   ↓
DNS
   ↓
MX Record
   ↓
Mail Server
</code></pre>
<h3>When a Service Verifies the Domain</h3>
<p>It may look for a specific <strong>TXT record</strong>.</p>
<p>And if someone uses <code>www.example.com</code>, a <strong>CNAME</strong> may tell DNS to use another domain name.</p>
<hr />
<h2>A vs CNAME: The Common Confusion</h2>
<p>A simple way to remember the difference:</p>
<p><strong>A record:</strong></p>
<blockquote>
<p>"This name has this IP address."</p>
</blockquote>
<p><strong>CNAME:</strong></p>
<blockquote>
<p>"This name is another name."</p>
</blockquote>
<p>So:</p>
<pre><code class="language-text">A:
example.com → 192.0.2.10

CNAME:
www.example.com → example.com
</code></pre>
<hr />
<h2>NS vs MX: Another Common Confusion</h2>
<p>These records are also easy to mix up.</p>
<p><strong>NS</strong> answers:</p>
<blockquote>
<p>"Which DNS servers are responsible for this domain?"</p>
</blockquote>
<p><strong>MX</strong> answers:</p>
<blockquote>
<p>"Which mail servers should receive email for this domain?"</p>
</blockquote>
<p>They both involve servers, but they solve completely different problems.</p>
<hr />
<h2>Final Mental Model</h2>
<p>You don't need to memorize complicated definitions. Just remember what question each record answers:</p>
<table>
<thead>
<tr>
<th>Record</th>
<th>Simple Question</th>
</tr>
</thead>
<tbody><tr>
<td><strong>NS</strong></td>
<td>Who manages this domain's DNS?</td>
</tr>
<tr>
<td><strong>A</strong></td>
<td>What is the IPv4 address?</td>
</tr>
<tr>
<td><strong>AAAA</strong></td>
<td>What is the IPv6 address?</td>
</tr>
<tr>
<td><strong>CNAME</strong></td>
<td>What other name should this name point to?</td>
</tr>
<tr>
<td><strong>MX</strong></td>
<td>Where should this domain's email go?</td>
</tr>
<tr>
<td><strong>TXT</strong></td>
<td>What extra information should be stored?</td>
</tr>
</tbody></table>
<p>A real domain uses these records together because a website is more than just a web server.</p>
<p>DNS can help your browser find the server, help mail systems find the email server, point different domain names to the same destination, identify who manages the domain, and provide verification information.</p>
<p>That is why DNS is often called the <strong>phonebook of the internet</strong>: it connects human-friendly names with the information computers and services need to communicate.</p>
]]></content:encoded></item><item><title><![CDATA[How DNS Resolution Works: A Practical Guide]]></title><description><![CDATA[You type google.com into your browser, press Enter, and the website appears.
But computers do not naturally communicate using names like google.com. They communicate using IP addresses such as 142.250]]></description><link>https://maazzz.hashnode.dev/how-dns-resolution-works-a-practical-guide</link><guid isPermaLink="true">https://maazzz.hashnode.dev/how-dns-resolution-works-a-practical-guide</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Sun, 09 Aug 2026 19:11:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/20824558-1f1c-41e4-bf4e-f119b1f2543d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You type <code>google.com</code> into your browser, press Enter, and the website appears.</p>
<p>But computers do not naturally communicate using names like <code>google.com</code>. They communicate using <strong>IP addresses</strong> such as <code>142.250.x.x</code>.</p>
<p>So how does your computer find the IP address behind a domain name?</p>
<p>This is where <strong>DNS (Domain Name System)</strong> comes in.</p>
<p>Think of DNS as the <strong>internet's phonebook</strong>. It translates human-readable domain names into IP addresses that computers can use to communicate.</p>
<p>In this article, we'll understand how <strong>DNS resolution</strong> works from the root DNS servers all the way to the authoritative name servers, using the <code>dig</code> command to inspect each step.</p>
<h2>What Is DNS Resolution?</h2>
<p><strong>DNS resolution</strong> is the process of finding the IP address associated with a domain name.</p>
<p>For example:</p>
<pre><code class="language-text">google.com
    ↓
DNS Resolution
    ↓
IP Address
    ↓
Browser connects to the server
</code></pre>
<p>The interesting part is that DNS is organized as a <strong>hierarchy</strong>.</p>
<p>A simplified DNS hierarchy looks like this:</p>
<pre><code class="language-text">                    Root (.)
                      |
                    .com
                      |
                 google.com
                      |
             Authoritative DNS
                      |
                IP Address
</code></pre>
<p>The three important levels are:</p>
<ol>
<li><p><strong>Root DNS servers</strong></p>
</li>
<li><p><strong>TLD name servers</strong></p>
</li>
<li><p><strong>Authoritative name servers</strong></p>
</li>
</ol>
<p>Before looking at each one, let's understand the tool we'll use.</p>
<h2>What Is <code>dig</code>?</h2>
<p><code>dig</code> stands for <strong>Domain Information Groper</strong>.</p>
<p>It is a command-line tool used to inspect DNS information and troubleshoot DNS problems.</p>
<p>For example:</p>
<pre><code class="language-bash">dig google.com
</code></pre>
<p>It can show information such as:</p>
<ul>
<li><p>DNS records</p>
</li>
<li><p>IP addresses</p>
</li>
<li><p>Name servers</p>
</li>
<li><p>Query status</p>
</li>
<li><p>Response time</p>
</li>
<li><p>Which server answered the query</p>
</li>
</ul>
<p>Instead of simply asking, "What IP address does this domain have?", <code>dig</code> lets us look deeper into <strong>how DNS works</strong>.</p>
<hr />
<h2>1. <code>dig . NS</code> — Finding Root Name Servers</h2>
<p>Start with:</p>
<pre><code class="language-bash">dig . NS
</code></pre>
<p>Here, <code>.</code> represents the <strong>DNS root</strong>.</p>
<p>The <code>NS</code> means <strong>Name Server</strong>.</p>
<p>An <strong>NS record</strong> tells us which DNS servers are responsible for a particular DNS zone.</p>
<p>So:</p>
<pre><code class="language-bash">dig . NS
</code></pre>
<p>asks:</p>
<blockquote>
<p>"Which name servers are responsible for the root DNS zone?"</p>
</blockquote>
<p>The response contains root name servers such as:</p>
<pre><code class="language-text">a.root-servers.net
b.root-servers.net
...
</code></pre>
<p>These are operated by different organizations around the world.</p>
<p>The root servers do <strong>not</strong> normally tell you the IP address of <code>google.com</code>.</p>
<p>Instead, they know where to find the next level: the <strong>TLD name servers</strong>.</p>
<hr />
<h2>2. <code>dig com NS</code> — Finding TLD Name Servers</h2>
<p>Next:</p>
<pre><code class="language-bash">dig com NS
</code></pre>
<p>Here, <code>com</code> represents the <code>.com</code> <strong>Top-Level Domain (TLD)</strong>.</p>
<p>This asks:</p>
<blockquote>
<p>"Which name servers are responsible for the <code>.com</code> domain?"</p>
</blockquote>
<p>The response provides name servers responsible for the <code>.com</code> TLD.</p>
<p>These are called <strong>TLD name servers</strong>.</p>
<p>Their job is not to know every domain's IP address. Instead, they know which <strong>authoritative name servers</strong> are responsible for individual domains under <code>.com</code>.</p>
<p>For example:</p>
<pre><code class="language-text">Root DNS
    |
    | Where is .com?
    ↓
.com TLD Servers
    |
    | Where is google.com?
    ↓
Google's Authoritative DNS
</code></pre>
<p>This hierarchical design allows DNS to scale to billions of domain names.</p>
<hr />
<h2>3. <code>dig google.com NS</code> — Finding Authoritative Name Servers</h2>
<p>Now run:</p>
<pre><code class="language-bash">dig google.com NS
</code></pre>
<p>This asks:</p>
<blockquote>
<p>"Which name servers are authoritative for <code>google.com</code>?"</p>
</blockquote>
<p>The response contains the <strong>authoritative name servers</strong> for the domain.</p>
<p>An authoritative DNS server is the server that has the official DNS information for a domain.</p>
<p>It can contain records such as:</p>
<ul>
<li><p><code>A</code> — IPv4 address</p>
</li>
<li><p><code>AAAA</code> — IPv6 address</p>
</li>
<li><p><code>MX</code> — Mail server</p>
</li>
<li><p><code>CNAME</code> — Alias</p>
</li>
<li><p><code>NS</code> — Name server</p>
</li>
<li><p><code>TXT</code> — Text information</p>
</li>
</ul>
<p>The important idea is:</p>
<blockquote>
<p><strong>Authoritative DNS servers are the source of truth for a DNS zone.</strong></p>
</blockquote>
<p>For <code>google.com</code>, its authoritative DNS infrastructure can provide the DNS records needed to resolve the domain.</p>
<hr />
<h2>4. <code>dig google.com</code> — Getting the IP Address</h2>
<p>Now run:</p>
<pre><code class="language-bash">dig google.com
</code></pre>
<p>This performs a DNS lookup for <code>google.com</code>.</p>
<p>The response commonly contains an <strong>A record</strong>, which maps the domain to an IPv4 address.</p>
<p>You may see something like:</p>
<pre><code class="language-text">google.com.    300    IN    A    142.250.x.x
</code></pre>
<p>The important parts are:</p>
<ul>
<li><p><strong>google.com</strong> — domain name</p>
</li>
<li><p><strong>300</strong> — TTL (how long the response can be cached)</p>
</li>
<li><p><strong>A</strong> — IPv4 address record</p>
</li>
<li><p><strong>142.250.x.x</strong> — returned IP address</p>
</li>
</ul>
<p>Your actual IP may differ because large services can use multiple addresses and DNS-based traffic distribution.</p>
<hr />
<h2>What Happens During Real DNS Resolution?</h2>
<p>When you enter:</p>
<pre><code class="language-text">https://google.com
</code></pre>
<p>your computer usually does <strong>not</strong> start by contacting a root server every time.</p>
<p>Instead, the request commonly goes through a <strong>recursive DNS resolver</strong>.</p>
<p>This resolver may be provided by your ISP, organization, router, or a public DNS service.</p>
<p>A simplified resolution flow looks like this:</p>
<pre><code class="language-text">Browser
   |
   | "What is the IP of google.com?"
   ↓
Recursive DNS Resolver
   |
   | 1. Ask Root
   ↓
Root DNS Servers
   |
   | "Ask the .com TLD servers"
   ↓
.com TLD Servers
   |
   | "Ask google.com's authoritative servers"
   ↓
Authoritative DNS Servers
   |
   | "Here is the DNS record"
   ↓
Recursive Resolver
   |
   | IP address
   ↓
Browser
</code></pre>
<p>The resolver performs the work on behalf of your computer.</p>
<h3>Why Does the Resolver Matter?</h3>
<p>The recursive resolver can <strong>cache</strong> DNS responses.</p>
<p>For example, if another user recently requested <code>google.com</code>, the resolver may already have its answer stored.</p>
<p>Then instead of repeating:</p>
<pre><code class="language-text">Root → TLD → Authoritative
</code></pre>
<p>it can return the cached result immediately, as long as the record's <strong>TTL (Time To Live)</strong> has not expired.</p>
<p>This makes DNS resolution faster and reduces unnecessary traffic to higher-level DNS servers.</p>
<hr />
<h2>Connecting <code>dig</code> to the Real World</h2>
<p>The commands we used represent different parts of the DNS hierarchy:</p>
<pre><code class="language-text">dig . NS
     ↓
Root DNS Servers

dig com NS
     ↓
.com TLD Name Servers

dig google.com NS
     ↓
Authoritative Name Servers

dig google.com
     ↓
DNS Record / IP Address
</code></pre>
<p>In a real browser request, these steps happen behind the scenes through a recursive resolver.</p>
<p>Once the browser receives the IP address, DNS has done its job.</p>
<p>The browser can then connect to that server using protocols such as <strong>TCP/IP and HTTP/HTTPS</strong>.</p>
<h2>Final Mental Model</h2>
<p>DNS is not one giant server containing every domain and IP address.</p>
<p>It is a <strong>distributed and hierarchical system</strong>.</p>
<p>Remember the flow:</p>
<pre><code class="language-text">Domain Name
     ↓
Recursive Resolver
     ↓
Root DNS
     ↓
TLD DNS
     ↓
Authoritative DNS
     ↓
DNS Record
     ↓
IP Address
</code></pre>
<p>And remember what each level does:</p>
<ul>
<li><p><strong>Root DNS:</strong> Points toward the correct TLD servers.</p>
</li>
<li><p><strong>TLD DNS:</strong> Points toward the domain's authoritative name servers.</p>
</li>
<li><p><strong>Authoritative DNS:</strong> Provides the actual DNS records for the domain.</p>
</li>
<li><p><strong>Recursive Resolver:</strong> Performs this lookup process for the client and caches the results.</p>
</li>
</ul>
<p>Once you understand this hierarchy, commands like <code>dig . NS</code>, <code>dig com NS</code>, <code>dig google.com NS</code>, and <code>dig google.com</code> stop looking like random commands and start showing you the actual structure behind <strong>DNS resolution on the internet</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[TCP: 3-Way Handshake & Reliable Data Transfer]]></title><description><![CDATA[Imagine sending data across the internet with no rules.
You send some data, but how does the receiver know where it came from? What if some data is lost? What if it arrives in the wrong order? How doe]]></description><link>https://maazzz.hashnode.dev/tcp-3-way-handshake-reliable-data-transfer</link><guid isPermaLink="true">https://maazzz.hashnode.dev/tcp-3-way-handshake-reliable-data-transfer</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Thu, 06 Aug 2026 18:37:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/a715020b-843a-4df9-820e-3d662622e6f7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine sending data across the internet with no rules.</p>
<p>You send some data, but how does the receiver know where it came from? What if some data is lost? What if it arrives in the wrong order? How does the sender know that the receiver is ready to communicate?</p>
<p>These are some of the problems <strong>TCP (Transmission Control Protocol)</strong> is designed to solve.</p>
<p>TCP is a <strong>connection-oriented transport-layer protocol</strong> that provides reliable, ordered, and error-checked delivery of data between applications.</p>
<h2>What Problems Does TCP Solve?</h2>
<p>Networks are not perfectly reliable. Data can be delayed, lost, duplicated, or arrive out of order.</p>
<p>TCP handles these problems by providing mechanisms such as:</p>
<ul>
<li><p><strong>Connection establishment</strong></p>
</li>
<li><p><strong>Sequence numbers</strong></p>
</li>
<li><p><strong>Acknowledgements</strong></p>
</li>
<li><p><strong>Retransmission</strong></p>
</li>
<li><p><strong>Ordered delivery</strong></p>
</li>
<li><p><strong>Flow control</strong></p>
</li>
<li><p><strong>Congestion control</strong></p>
</li>
<li><p><strong>Connection termination</strong></p>
</li>
</ul>
<p>Before TCP transfers application data, it first establishes a connection using the <strong>3-way handshake</strong>.</p>
<h2>TCP 3-Way Handshake</h2>
<p>The handshake allows both sides to establish communication and synchronize their initial sequence numbers.</p>
<p>Think of it like a conversation:</p>
<blockquote>
<p><strong>Client:</strong> "Can we communicate?"</p>
</blockquote>
<blockquote>
<p><strong>Server:</strong> "Yes, I can communicate. Can you hear me?"</p>
</blockquote>
<blockquote>
<p><strong>Client:</strong> "Yes, I can hear you."</p>
</blockquote>
<p>Now both sides are ready to exchange data.</p>
<p>The actual process uses three TCP messages: <strong>SYN, SYN-ACK, and ACK</strong>.</p>
<h3>Step 1: SYN</h3>
<p>The client sends a <strong>SYN (Synchronize)</strong> segment to the server.</p>
<p>It basically says:</p>
<blockquote>
<p>"I want to establish a TCP connection."</p>
</blockquote>
<p>The client also includes an <strong>initial sequence number</strong>. Sequence numbers help TCP keep track of the position of data in the communication stream.</p>
<pre><code class="language-text">Client                         Server
   |                             |
   | -------- SYN -------------&gt; |
   |                             |
</code></pre>
<h3>Step 2: SYN-ACK</h3>
<p>The server receives the SYN and responds with <strong>SYN-ACK</strong>.</p>
<p>This message does two things:</p>
<ol>
<li><p><strong>SYN:</strong> The server provides its own initial sequence number.</p>
</li>
<li><p><strong>ACK:</strong> The server acknowledges the client's SYN.</p>
</li>
</ol>
<p>In simple terms:</p>
<blockquote>
<p>"I received your request, and I also want to communicate."</p>
</blockquote>
<pre><code class="language-text">Client                         Server
   |                             |
   | -------- SYN -------------&gt; |
   | &lt;------ SYN + ACK ---------- |
   |                             |
</code></pre>
<h3>Step 3: ACK</h3>
<p>Finally, the client sends an <strong>ACK (Acknowledgement)</strong> back to the server.</p>
<p>This confirms that the client's side has received the server's response.</p>
<pre><code class="language-text">Client                         Server
   |                             |
   | -------- SYN -------------&gt; |
   | &lt;------ SYN + ACK ---------- |
   | -------- ACK -------------&gt; |
   |                             |
</code></pre>
<p>The connection is now established, and application data can be transferred.</p>
<h2>How Does TCP Transfer Data?</h2>
<p>Once the connection exists, the application passes data to TCP.</p>
<p>TCP assigns <strong>sequence numbers</strong> to the data so that the receiver can determine its correct order.</p>
<p>The receiver sends <strong>ACKs</strong> to confirm that data has been received.</p>
<p>For example:</p>
<pre><code class="language-text">Client                         Server

Data: Seq 1000  -------------&gt;

              &lt;------------- ACK 1500
</code></pre>
<p>The exact numbers depend on the amount of data being transmitted, but the basic idea is simple:</p>
<p><strong>Sequence numbers identify data; acknowledgements confirm received data.</strong></p>
<h3>What If Data Gets Lost?</h3>
<p>Suppose the sender transmits three pieces of data, but one never reaches the receiver.</p>
<p>TCP can detect the missing data through its acknowledgement and retransmission mechanisms.</p>
<pre><code class="language-text">Client                         Server

Segment 1 -------------------&gt;
Segment 2 --------X (lost)

Segment 3 -------------------&gt;

        &lt;-------------------- ACK

Segment 2 -------------------&gt;
</code></pre>
<p>TCP can then retransmit the missing data.</p>
<p>This is one of the main reasons TCP is considered <strong>reliable</strong>.</p>
<p>TCP also makes sure data is delivered to the application in the correct order, even if network packets arrive out of order.</p>
<h2>How Does TCP Know When to Retransmit?</h2>
<p>TCP does not wait forever for a missing acknowledgement.</p>
<p>It uses <strong>timers</strong> and other mechanisms to determine when data may need to be retransmitted.</p>
<p>TCP also uses a process called <strong>flow control</strong> to prevent a sender from overwhelming the receiver and <strong>congestion control</strong> to adjust transmission when the network itself becomes congested.</p>
<p>These mechanisms allow TCP to provide reliable communication while adapting to changing network conditions.</p>
<h2>How Does TCP Connection Closing Work?</h2>
<p>TCP also has a controlled process for ending a connection.</p>
<p>Unlike the 3-way handshake used for establishing a connection, normal TCP termination commonly involves <strong>FIN and ACK messages in both directions</strong> because TCP communication is full-duplex: each side can send data independently.</p>
<p>A simplified flow looks like this:</p>
<pre><code class="language-text">Client                         Server

   | -------- FIN ------------&gt; |
   | &lt;--------- ACK ----------- |
   | &lt;--------- FIN ----------- |
   | -------- ACK ------------&gt; |
</code></pre>
<p><strong>FIN</strong> means a side has finished sending data.</p>
<p><strong>ACK</strong> confirms that the FIN was received.</p>
<p>After both directions have been closed, the TCP connection is terminated.</p>
<h2>TCP Connection Lifecycle</h2>
<p>The complete lifecycle can be simplified as:</p>
<pre><code class="language-text">Connection Establishment
        ↓
   SYN → SYN-ACK → ACK
        ↓
     Data Transfer
        ↓
Sequence Numbers + ACKs
        ↓
     Connection Close
        ↓
    FIN → ACK → FIN → ACK
</code></pre>
<h2>Final Takeaway</h2>
<p>TCP is more than simply "sending data reliably."</p>
<p>It first <strong>establishes a connection</strong>, then uses <strong>sequence numbers, acknowledgements, retransmission, flow control, and congestion control</strong> to manage data transfer. Finally, it uses <strong>FIN and ACK messages</strong> to close the connection properly.</p>
<p>The easiest mental model is:</p>
<blockquote>
<p><strong>Handshake before communication, sequence and acknowledgement during communication, and FIN/ACK when communication ends.</strong></p>
</blockquote>
<p>That process is what allows applications to communicate reliably even though the underlying network can lose, delay, or reorder data.</p>
]]></content:encoded></item><item><title><![CDATA[TCP vs UDP: How Data Travels Across the Internet]]></title><description><![CDATA[Whenever you open a website, send a message, watch a video, or play an online game, data is constantly moving between your device and another computer.
But how does that communication happen?
Computer]]></description><link>https://maazzz.hashnode.dev/tcp-vs-udp-how-data-travels-across-the-internet</link><guid isPermaLink="true">https://maazzz.hashnode.dev/tcp-vs-udp-how-data-travels-across-the-internet</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Thu, 06 Aug 2026 18:22:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/7a0516ba-8f21-4a2c-94d8-719c89e03bf2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whenever you open a website, send a message, watch a video, or play an online game, data is constantly moving between your device and another computer.</p>
<p><em>But how does that communication happen?</em></p>
<p>Computers need <strong>rules for sending and receiving data</strong>. These rules are called <strong>network protocols</strong>. Different protocols handle different parts of communication.</p>
<p>Two important protocols at the transport layer are <strong>TCP</strong> and <strong>UDP</strong>. They both transport data between applications, but they make very different trade-offs.</p>
<h2>What Are TCP and UDP?</h2>
<p><strong>TCP (Transmission Control Protocol)</strong> is a <strong>connection-oriented and reliable</strong> transport protocol.</p>
<p>Before application data is exchanged, TCP establishes a connection between the sender and receiver. It then provides mechanisms to make sure data is delivered correctly and in the right order.</p>
<p><strong>UDP (User Datagram Protocol)</strong> is a <strong>connectionless and lightweight</strong> transport protocol.</p>
<p>It sends data without first establishing a connection and does not guarantee delivery, ordering, or retransmission.</p>
<p>A simple analogy helps:</p>
<ul>
<li><p><strong>TCP is like a phone call:</strong> you establish a connection and communicate while keeping track of the conversation.</p>
</li>
<li><p><strong>UDP is like an announcement:</strong> you send the information immediately without waiting for every listener to confirm that they received it.</p>
</li>
</ul>
<h2>How TCP Provides Reliable Communication</h2>
<p>TCP does more than simply send data.</p>
<p>When an application sends data, TCP divides the data into smaller pieces called <strong>segments</strong>. Each segment contains information such as sequence numbers that help the receiver identify its position in the overall data stream.</p>
<p>The receiver sends <strong>acknowledgments (ACKs)</strong> to tell the sender what data has been received.</p>
<p>If a segment is lost, TCP can detect that the expected data has not arrived and <strong>retransmit it</strong>.</p>
<p>TCP also ensures that data is delivered to the application in the correct order, even if network packets arrive out of order.</p>
<p>It also provides <strong>flow control</strong>, preventing a fast sender from overwhelming a slower receiver, and <strong>congestion control</strong>, which adjusts transmission behavior when the network becomes congested.</p>
<p>This reliability comes with additional overhead and can increase delay.</p>
<h2>How UDP Works Differently</h2>
<p>UDP takes a much simpler approach.</p>
<p>It does not establish a connection before sending data. It also does not provide built-in mechanisms for:</p>
<ul>
<li><p>Delivery confirmation</p>
</li>
<li><p>Retransmission</p>
</li>
<li><p>Ordering</p>
</li>
<li><p>Flow control</p>
</li>
<li><p>Congestion control</p>
</li>
</ul>
<p>Each UDP datagram is treated independently.</p>
<p>If a packet is lost, UDP itself does not resend it. If packets arrive out of order, UDP does not rearrange them.</p>
<p>This may sound like a disadvantage, but sometimes <strong>waiting for perfect delivery is worse than losing a small amount of data</strong>.</p>
<p>That is why UDP is useful for applications where low delay matters.</p>
<h2>TCP vs UDP</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>TCP</th>
<th>UDP</th>
</tr>
</thead>
<tbody><tr>
<td>Connection</td>
<td>Connection-oriented</td>
<td>Connectionless</td>
</tr>
<tr>
<td>Delivery</td>
<td>Reliable</td>
<td>No guarantee</td>
</tr>
<tr>
<td>Ordering</td>
<td>Guaranteed</td>
<td>Not guaranteed</td>
</tr>
<tr>
<td>Retransmission</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Flow control</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Congestion control</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Overhead</td>
<td>Higher</td>
<td>Lower</td>
</tr>
<tr>
<td>Typical priority</td>
<td>Accuracy</td>
<td>Speed and low delay</td>
</tr>
</tbody></table>
<h2>When Should You Use TCP?</h2>
<p>Use TCP when <strong>the complete and correct data matters more than immediate delivery</strong>.</p>
<p>Common examples include:</p>
<ul>
<li><p>Web applications</p>
</li>
<li><p>File downloads and uploads</p>
</li>
<li><p>Email</p>
</li>
<li><p>Database connections</p>
</li>
<li><p>APIs</p>
</li>
</ul>
<p>For example, imagine downloading a PDF. If some data is missing, the file could become corrupted. It is better to wait for retransmission than to receive an incomplete file.</p>
<p>TCP is like a <strong>courier service</strong>: the package should arrive completely and in the correct order.</p>
<h2>When Should You Use UDP?</h2>
<p>Use UDP when <strong>speed and low latency are more important than perfect delivery</strong>.</p>
<p>Common examples include:</p>
<ul>
<li><p>Online gaming</p>
</li>
<li><p>Voice calls</p>
</li>
<li><p>Video calls</p>
</li>
<li><p>Live communication</p>
</li>
<li><p>DNS queries</p>
</li>
<li><p>Some streaming and real-time systems</p>
</li>
</ul>
<p>Consider a video call. If one small piece of video is lost, stopping the entire call to retransmit it may create noticeable delay.</p>
<p>It is usually better to continue the conversation and accept a small glitch.</p>
<p>UDP is like a <strong>live broadcast</strong>: if one moment is missed, continuing the broadcast is more useful than stopping to replay it.</p>
<h2>Where Does HTTP Fit?</h2>
<p>This leads to a common beginner question:</p>
<blockquote>
<p><strong>Is HTTP the same as TCP?</strong></p>
</blockquote>
<p>No.</p>
<p><strong>HTTP (Hypertext Transfer Protocol)</strong> and TCP operate at different layers and solve different problems.</p>
<p>HTTP is an <strong>application-layer protocol</strong>. It defines how applications communicate using concepts such as:</p>
<ul>
<li><p>Requests and responses</p>
</li>
<li><p>HTTP methods such as <code>GET</code> and <code>POST</code></p>
</li>
<li><p>Headers</p>
</li>
<li><p>Status codes</p>
</li>
<li><p>Resources such as web pages and API data</p>
</li>
</ul>
<p>TCP is a <strong>transport-layer protocol</strong>. Its job is to transport application data between two endpoints reliably.</p>
<p>A simplified view looks like this:</p>
<pre><code class="language-text">Application Layer
        HTTP
         ↓
Transport Layer
        TCP
         ↓
Internet Layer
         IP
         ↓
      Network
</code></pre>
<p>When a browser requests a webpage using traditional HTTP, the HTTP request becomes application data that is passed down to TCP.</p>
<p>TCP transports that data across the network, while IP handles addressing and routing.</p>
<p>So, <strong>HTTP does not replace TCP</strong>.</p>
<p>A useful way to remember their relationship is:</p>
<blockquote>
<p><strong>HTTP defines what the application wants to communicate; TCP provides reliable transport for that communication.</strong></p>
</blockquote>
<h2>The Big Picture</h2>
<pre><code class="language-text">Browser
   │
   │ HTTP Request
   ↓
   TCP
   │
   │ Reliable Transport
   ↓
   IP
   │
   │ Routing
   ↓
Network
</code></pre>
<p>The important idea is not that TCP is always better than UDP.</p>
<p>They are designed for different needs:</p>
<p><strong>TCP prioritizes reliability and correctness. UDP prioritizes simplicity, speed, and low latency. HTTP sits above the transport layer and defines how web applications communicate.</strong></p>
<p>Once you understand these responsibilities, the relationship between <strong>HTTP, TCP, UDP, and IP</strong> becomes much easier to understand.</p>
]]></content:encoded></item><item><title><![CDATA[JavaScript Polyfills Explained]]></title><description><![CDATA[Introduction
JavaScript gives developers many powerful built-in methods that we use every day.
For example:
const numbers = [1, 2, 3, 4]; 
const doubled = numbers.map(num => num * 2);
console.log(doub]]></description><link>https://maazzz.hashnode.dev/javascript-polyfills-explained</link><guid isPermaLink="true">https://maazzz.hashnode.dev/javascript-polyfills-explained</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Sat, 11 Jul 2026 14:10:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/4fc7e869-564f-4bdd-881e-664dce22b77e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Introduction</h3>
<p>JavaScript gives developers many powerful built-in methods that we use every day.</p>
<p><strong>For example:</strong></p>
<pre><code class="language-javascript">const numbers = [1, 2, 3, 4]; 
const doubled = numbers.map(num =&gt; num * 2);
console.log(doubled);
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-javascript">[2, 4, 6, 8]
</code></pre>
<p><strong>Methods like:</strong></p>
<ul>
<li><p>map()</p>
</li>
<li><p>filter()</p>
</li>
<li><p>reduce()</p>
</li>
<li><p>includes()</p>
</li>
<li><p>trim()</p>
</li>
<li><p>Promise.all()</p>
</li>
</ul>
<p>make our code shorter and easier to write.</p>
<p>But have you ever wondered:</p>
<ul>
<li><p>How do these methods work internally?</p>
</li>
<li><p>What happens when a browser does not support a newer JavaScript feature?</p>
</li>
<li><p>How do developers use modern APIs while maintaining compatibility?</p>
</li>
</ul>
<blockquote>
<p>The answer is polyfills.</p>
</blockquote>
<hr />
<h3>What Are Polyfills?</h3>
<blockquote>
<p>A polyfill is a piece of JavaScript code that provides functionality that is missing in a browser or runtime environment.</p>
</blockquote>
<p><strong>In simple words:</strong></p>
<p><em>A polyfill fills the gap between what JavaScript provides and what the current environment supports.</em></p>
<p><strong>For example</strong>, modern browsers support:</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
numbers.map(num =&gt; num * 2);
</code></pre>
<p>But an older environment might not understand the <code>map()</code>method.</p>
<p>A developer can provide a custom implementation:</p>
<pre><code class="language-javascript">if (!Array.prototype.map) {
Array.prototype.map = function(callback) {
    // custom implementation
};
}
</code></pre>
<p><code>Now the missing functionality is available.</code></p>
<hr />
<h3>Why Do Developers Write Polyfills?</h3>
<p>JavaScript is constantly evolving.</p>
<p>New features are added through ECMAScript updates:</p>
<table>
<thead>
<tr>
<th>Version</th>
<th>Year</th>
<th>Examples</th>
</tr>
</thead>
<tbody><tr>
<td><strong>ES5</strong></td>
<td>2009</td>
<td><code>map()</code>, <code>filter()</code>, <code>reduce()</code>, <code>trim()</code></td>
</tr>
<tr>
<td><strong>ES6</strong></td>
<td>2015</td>
<td><code>Promise</code>, <code>find()</code>, <code>startsWith()</code></td>
</tr>
<tr>
<td><strong>ES2019</strong></td>
<td>2019</td>
<td><code>flat()</code></td>
</tr>
<tr>
<td><strong>ES2023</strong></td>
<td>2023</td>
<td><code>findLast()</code>, <code>toSorted()</code></td>
</tr>
<tr>
<td><strong>ES2024</strong></td>
<td>2024</td>
<td><code>Object.groupBy()</code>, <code>Promise.withResolvers()</code></td>
</tr>
</tbody></table>
<p>The <strong>problem</strong> is that browsers do not adopt new features at the same time.</p>
<p><em>A feature can exist in the JavaScript specification but still be unavailable in some environments.</em></p>
<blockquote>
<p>Polyfills solve this compatibility problem.</p>
</blockquote>
<p><em><strong>Common Use Cases of Polyfills</strong></em></p>
<p><strong>1. Browser Compatibility</strong></p>
<p>A website may have users using different browsers and versions.</p>
<p>Instead of avoiding modern JavaScript features, developers can provide fallback implementations.</p>
<p><strong>Example:</strong></p>
<pre><code class="language-javascript">array.find()
</code></pre>
<p>If the environment does not support it, a polyfill can provide similar behavior.</p>
<hr />
<p><strong>2. Supporting Legacy Applications</strong></p>
<p>Large applications often need to support older environments.</p>
<p>Polyfills allow developers to write modern JavaScript while keeping existing users supported.</p>
<hr />
<p><strong>3. Understanding JavaScript Internals</strong></p>
<p>Writing polyfills is also a great way to understand how JavaScript actually works.</p>
<p><strong>Implementing:</strong></p>
<pre><code class="language-javascript">map()
</code></pre>
<p><strong>teaches:</strong></p>
<ul>
<li><p>callbacks</p>
</li>
<li><p>arrays</p>
</li>
<li><p>iteration</p>
</li>
<li><p>return values</p>
</li>
</ul>
<p><strong>Implementing:</strong></p>
<pre><code class="language-javascript">Promise.all()
</code></pre>
<p><strong>teaches:</strong></p>
<ul>
<li><p>asynchronous execution</p>
</li>
<li><p>promise resolution</p>
</li>
<li><p>error handling</p>
</li>
</ul>
<hr />
<h3>How Do Polyfills Work?</h3>
<p>To understand polyfills, we first need to understand prototypes.</p>
<p>JavaScript uses prototype-based inheritance.</p>
<p><strong>Consider:</strong></p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
</code></pre>
<p><strong>This array can use methods like:</strong></p>
<pre><code class="language-javascript">numbers.map();
numbers.filter();
numbers.reduce();
</code></pre>
<p>But these methods are not stored inside every array.</p>
<p><strong>They exist on:</strong></p>
<pre><code class="language-javascript">Array.prototype
</code></pre>
<p><strong>You can check:</strong></p>
<pre><code class="language-javascript">console.log(Array.prototype);
</code></pre>
<p><strong>It contains methods like:</strong></p>
<p><code>map() filter() reduce()</code></p>
<p><strong>When JavaScript executes:</strong></p>
<pre><code class="language-javascript">numbers.map()
</code></pre>
<p>it looks for <strong>map()</strong> in the prototype chain:</p>
<pre><code class="language-plaintext">numbers
   |
   ↓
Array.prototype
   |
   ↓
map()
</code></pre>
<hr />
<h3>Creating Our First Polyfill</h3>
<p>Let's recreate a simplified version of map().</p>
<p><strong>The original method:</strong></p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
const result = numbers.map(num =&gt; num * 2);
console.log(result);
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-javascript">[2, 4, 6]
</code></pre>
<p><strong>Now let's create our own:</strong></p>
<pre><code class="language-javascript">Array.prototype.myMap = function(callback) {
const result = [];
for(let i = 0; i &lt; this.length; i++) {
    result.push(
        callback(this[i], i, this)
    );
}
return result;
};
</code></pre>
<p><strong>Usage:</strong></p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
const doubled = numbers.myMap( num =&gt; num * 2 );
console.log(doubled);
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-javascript">[2, 4, 6] 
</code></pre>
<hr />
<h3>Understanding The Implementation</h3>
<p><strong>The <mark class="bg-yellow-200 dark:bg-yellow-500/30">this</mark> Keyword</strong></p>
<p>Inside the method:</p>
<p><code>this</code></p>
<p><em>refers to the array that called the function.</em></p>
<p><strong>Example:</strong></p>
<pre><code class="language-javascript">numbers.myMap()
</code></pre>
<p><strong>means:</strong></p>
<p><code>this = numbers</code></p>
<hr />
<p><strong>Creating a New Array</strong></p>
<pre><code class="language-javascript">const result = [];
</code></pre>
<p><strong>map()</strong> does not modify the original array.</p>
<p><strong>Example:</strong></p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
const doubled = numbers.map( num =&gt; num * 2 );
console.log(numbers);
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-javascript">[1, 2, 3]
</code></pre>
<p><em>The original array remains unchanged.</em></p>
<hr />
<p><strong>Callback Function</strong></p>
<p>The callback receives:</p>
<p><code>callback(value, index, array)</code></p>
<p><strong>Example:</strong></p>
<pre><code class="language-javascript">numbers.map(
    (value, index, array) =&gt; {
    }
);
</code></pre>
<p><strong>It provides:</strong></p>
<ul>
<li><p>Current value</p>
</li>
<li><p>Current index</p>
</li>
<li><p>Original array</p>
</li>
</ul>
<hr />
<h3>The Standard Polyfill Pattern</h3>
<p><em>A good polyfill should not replace the browser's native implementation.</em></p>
<p>The common approach is:</p>
<pre><code class="language-javascript">if (!Array.prototype.myMethod) {
    Array.prototype.myMethod = function() {
        // implementation
    };
}
</code></pre>
<p><strong>This means:</strong></p>
<blockquote>
<p>Add the feature only when it does not already exist.</p>
</blockquote>
<p>This allows modern browsers to continue using their optimized native implementations.</p>
<hr />
<h3>Common Categories of Polyfills</h3>
<p>Polyfills are <strong>not a special type of JavaScript feature</strong>. They're simply fallback implementations written when a browser or runtime doesn't support a built-in API.</p>
<p>In practice, developers usually organize polyfills based on the JavaScript object they extend. Some of the most common categories include:</p>
<table>
<thead>
<tr>
<th>Category</th>
<th>Common Examples</th>
</tr>
</thead>
<tbody><tr>
<td>Array Methods</td>
<td><code>map()</code>, <code>filter()</code>, <code>reduce()</code>, <code>find()</code>, <code>flat()</code>, <code>findLast()</code>, <code>toSorted()</code></td>
</tr>
<tr>
<td>String Methods</td>
<td><code>trim()</code>, <code>includes()</code>, <code>startsWith()</code>, <code>endsWith()</code></td>
</tr>
<tr>
<td>Object Methods</td>
<td><code>Object.keys()</code>, <code>Object.assign()</code>, <code>Object.groupBy()</code></td>
</tr>
<tr>
<td>Promise Methods</td>
<td><code>Promise.all()</code>, <code>Promise.withResolvers()</code></td>
</tr>
</tbody></table>
<p>Each category helps us understand a different part of JavaScript. For example, array polyfills teach iteration and callbacks, string polyfills focus on text manipulation, object polyfills deal with object operations, and promise polyfills introduce asynchronous programming.</p>
<p>Since we've already built our first <code>map()</code> polyfill, the same idea can be applied to many other built-in methods <em>whenever native support is unavailable.</em></p>
<hr />
<h3>What Are String Methods?</h3>
<p>Just as arrays have built-in methods, strings also provide useful methods for working with text. They're commonly used to validate user input, search text, format strings, and clean data before processing.</p>
<p><strong>Some frequently used string methods include:</strong></p>
<ul>
<li><p><code>trim()</code></p>
</li>
<li><p><code>includes()</code></p>
</li>
<li><p><code>startsWith()</code></p>
</li>
<li><p><code>endsWith()</code></p>
</li>
<li><p><code>replace()</code></p>
</li>
</ul>
<p>Like array methods, these can also be polyfilled when required.</p>
<hr />
<h3>Implementing Simple String Utilities</h3>
<p>The implementation pattern remains exactly the same as our <code>map()</code> polyfill:</p>
<ul>
<li><p>Extend <code>String.prototype</code></p>
</li>
<li><p>Access the current string using <code>this</code></p>
</li>
<li><p>Return the expected result</p>
</li>
</ul>
<p><strong>For example</strong>, a simple <code>trim()</code> polyfill looks like this:</p>
<pre><code class="language-javascript">String.prototype.myTrim = function () {
    return this.replace(/^\s+|\s+$/g, "");
};
</code></pre>
<p>Once you understand one polyfill, creating similar utilities for methods like <code>includes()</code> or <code>startsWith()</code> becomes much easier.</p>
<hr />
<h3>Polyfills and JavaScript Interviews</h3>
<p>If you've ever been asked to implement your own <code>map()</code>, <code>filter()</code>, or <code>reduce()</code> during an interview, you've already encountered a polyfill-style question.</p>
<p>Interviewers aren't expecting you to recreate the exact browser implementation. Instead, they want to evaluate your understanding of:</p>
<ul>
<li><p>Prototypes</p>
</li>
<li><p>Loops and iteration</p>
</li>
<li><p>Callback functions</p>
</li>
<li><p>Return values</p>
</li>
<li><p>Problem-solving skills</p>
</li>
</ul>
<p><strong>Questions like these are common:</strong></p>
<ul>
<li><p>Implement your own <code>map()</code></p>
</li>
<li><p>Create a custom <code>filter()</code></p>
</li>
<li><p>Write your own <code>reduce()</code></p>
</li>
<li><p>Implement <code>Promise.all()</code></p>
</li>
</ul>
<p>If you've built polyfills before, these questions become much easier because you already understand how these methods work behind the scenes.</p>
<hr />
<h3>Why Understanding Built-in Behavior Matters</h3>
<p>It's easy to use JavaScript's built-in methods, but understanding how they work internally makes you a stronger developer.</p>
<p>Building polyfills helps you:</p>
<ul>
<li><p>Write cleaner and more predictable code.</p>
</li>
<li><p>Debug issues more confidently.</p>
</li>
<li><p>Understand new JavaScript features faster.</p>
</li>
<li><p>Perform better in JavaScript interviews.</p>
</li>
</ul>
<p>More importantly, it changes the way you think about the language. Instead of treating built-in methods as "magic," you understand the logic behind them.</p>
<hr />
<h3>Final Take</h3>
<p>Polyfills are much more than browser compatibility tools—<em>they're one of the best ways to learn JavaScript from the inside out.</em></p>
<p>By recreating built-in methods yourself, you gain a deeper understanding of how the language works, making it easier to write better code and confidently tackle interview questions.</p>
<p>If you'd like to explore complete implementations of these polyfills, including <strong>Array</strong>, <strong>String</strong>, <strong>Object</strong>, and <strong>Promise</strong> methods, check out my GitHub repository:</p>
<p><strong>GitHub Repository:</strong> <a href="https://github.com/maazhafeez698/js-polyfills">js-polyfils</a></p>
]]></content:encoded></item><item><title><![CDATA[Git for Beginners: Learn What Matters]]></title><description><![CDATA[If you’ve ever written code and thought,"What if I break something… or lose everything?" — you’re not alone.
That’s exactly the problem Git solves.
In this guide, I’ll explain Git in the simplest way ]]></description><link>https://maazzz.hashnode.dev/git-for-beginners-learn-what-matters</link><guid isPermaLink="true">https://maazzz.hashnode.dev/git-for-beginners-learn-what-matters</guid><dc:creator><![CDATA[Maaz Hafeez]]></dc:creator><pubDate>Sun, 12 Apr 2026 15:26:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69daf17baadf1107e27851eb/33d05de2-8088-4ea0-a00c-b957880a32d5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve ever written code and thought,<br />"What if I break something… or lose everything?" — you’re not alone.</p>
<p>That’s exactly the problem Git solves.</p>
<p>In this guide, I’ll explain Git in the simplest way possible—no confusing jargon, just real understanding.</p>
<h2>What is Git? (In Simple Words)</h2>
<p>Git is a code tracker.<br />It tracks your code line by line, so you always know:</p>
<ul>
<li><p>what changed</p>
</li>
<li><p>when it changed</p>
</li>
<li><p>who changed it</p>
</li>
</ul>
<p>Think of it like a time machine for your code.</p>
<h2>Example (How Git Tracks Changes)</h2>
<p>Let’s say you wrote this:</p>
<p>const name = "Maaz"</p>
<p>Then later, you changed it:</p>
<ul>
<li><p>const name = "Maaz"</p>
</li>
<li><p>const name = "Maazzz"</p>
</li>
</ul>
<p>Git doesn’t just store the new version. It stores the difference (called a “diff”).</p>
<p>You can see this difference using command:</p>
<p>git diff</p>
<p>So you can:</p>
<ul>
<li><p>Go back to the old version</p>
</li>
<li><p>Compare changes</p>
</li>
<li><p>Understand what was modified</p>
</li>
</ul>
<h2>How Git Works (Simple Idea)</h2>
<p>Git uses a technique called version control:</p>
<ul>
<li><p>It takes snapshots of your project</p>
</li>
<li><p>Each snapshot is a version</p>
</li>
<li><p>You can move between versions anytime</p>
</li>
</ul>
<p>Imagine saving your file like:</p>
<p>project_v1<br />project_v2<br />project_final<br />project_final_final</p>
<p>Git automates this properly.</p>
<h2>Why Git is Used (Problem → Solution)</h2>
<h3>Before Git (Big Problem)</h3>
<p>Developers used to:</p>
<ul>
<li><p>Save files manually</p>
</li>
<li><p>Share code via USB or email</p>
</li>
<li><p>Overwrite each other’s work</p>
</li>
</ul>
<h3>Result:</h3>
<ul>
<li><p>Lost code</p>
</li>
<li><p>Conflicts</p>
</li>
<li><p>Confusion</p>
</li>
</ul>
<h2>Pendrive Solution (Old Approach)</h2>
<p>People tried copying projects using a pendrive.</p>
<h3>Problems:</h3>
<ul>
<li><p>Only one person can work at a time</p>
</li>
<li><p>No history tracking</p>
</li>
<li><p>Easy to lose data</p>
</li>
<li><p>No collaboration</p>
</li>
</ul>
<h2>The Real Solution (Git + Servers)</h2>
<p>Now imagine the same pendrive, but on the internet.</p>
<p>That’s Git with platforms like GitHub, GitLab, and Bitbucket.</p>
<h3>Benefits:</h3>
<ul>
<li><p>Multiple people can work together</p>
</li>
<li><p>Everything is tracked</p>
</li>
<li><p>No data loss</p>
</li>
<li><p>One single source of truth</p>
</li>
</ul>
<p>This is what Git solves.</p>
<h2>Git Basics and Core Terminologies</h2>
<p>Before commands, understand these:</p>
<p><strong>Repository (Repo):</strong> Your project folder tracked by Git</p>
<p><strong>Commit:</strong> A saved version (snapshot) of your code</p>
<p><strong>Branch:</strong> A separate version of your project used to test features</p>
<p><strong>Merge:</strong> Combining changes from one branch to another</p>
<p><strong>Staging Area:</strong> A place where changes are prepared before committing</p>
<h3>Simple flow:</h3>
<p>Working → Staging → Commit → History</p>
<h2>How to Set Up Git in Your Project</h2>
<p><strong>1. Install Git</strong><br />Download from <a href="https://git-scm.com">https://git-scm.com</a></p>
<p><strong>2. Configure Git (First Time Only)</strong><br />git config --global user.name "Your Name"<br />git config --global user.email "<a href="mailto:your@email.com">your@email.com</a>"<br />Sets your identity for commits.</p>
<p><strong>3. Initialize Git in Your Project</strong><br />git init<br />Starts tracking your project</p>
<p><strong>4. Add Files</strong><br />git add .<br />Moves your changes to the staging area.</p>
<p><strong>5. Commit Changes</strong><br />git commit -m "Initial commit"<br />Saves a snapshot of your project.</p>
<p><strong>6. Connect to Remote Repository</strong><br />git remote add origin<br />git push -u origin main<br />Uploads your project online.</p>
<h2>Top 10 Most Used Git Commands</h2>
<p><strong>1. Initialize</strong><br />Git git init<br />Starts a new Git repository</p>
<p><strong>2. Check Status</strong><br />git status<br />Shows current changes and file states</p>
<p><strong>3. Add Files</strong><br />git add .<br />Stages all changes for commit</p>
<p><strong>4. Commit Changes</strong><br />git commit -m "message"<br />Saves changes with a message</p>
<p><strong>5. View History</strong><br />git log<br />Displays commit history</p>
<p><strong>6. Create Branch</strong><br />git branch feature-name<br />Creates a new branch</p>
<p><strong>7. Switch Branch</strong><br />git checkout feature-name<br />Moves to another branch</p>
<p><strong>8. Merge Branch</strong><br />git merge feature-name<br />Combines another branch into current branch</p>
<p><strong>9. Push Code</strong><br />git push<br />Uploads commits to remote repository</p>
<p><strong>10. Pull Latest Code</strong><br />git pull<br />Fetches and updates local code with remote changes</p>
<h2>Final Thoughts</h2>
<p>Git might feel confusing at first, but it is simple.</p>
<p>It:</p>
<ul>
<li><p>Tracks changes</p>
</li>
<li><p>Saves versions</p>
</li>
<li><p>Helps teams collaborate</p>
</li>
</ul>
<h3>Remember:</h3>
<p>you don’t need to learn everything at once start with basic commands practice regularly.</p>
]]></content:encoded></item></channel></rss>