Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions docs/beyond/concepts/blob-file-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
title: "Blob & File API in JavaScript"
sidebarTitle: "Blob & File API"
description: "Learn JavaScript Blob and File APIs for binary data. Create, read, and manipulate files, handle uploads, generate downloads, and work with FileReader."
"og:type": "article"
"article:author": "Leonardo Maldonado"
"article:section": "Data Handling"
"article:tag": "blob file api, file upload, filereader, binary data, file download, file handling"
---

How do you let users upload images? How do you create a downloadable file from data generated in JavaScript? How can you read the contents of a file the user selected?
Expand Down Expand Up @@ -43,9 +47,9 @@ Understanding these APIs unlocks powerful client-side file handling without need

## What is a Blob in JavaScript?

A **[Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)** (Binary Large Object) is an immutable, file-like object that represents raw binary data. Think of it as a container that can hold any kind of data: text, images, audio, video, or arbitrary bytes. Blobs are the foundation for file handling in JavaScript, as the File interface is built on top of Blob.
A **[Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)** (Binary Large Object) is an immutable, file-like object that represents raw binary data. According to the [W3C File API specification](https://www.w3.org/TR/FileAPI/#blob-section), a Blob is a container that can hold any kind of data: text, images, audio, video, or arbitrary bytes. Blobs are the foundation for file handling in JavaScript, as the File interface is built on top of Blob.

Unlike regular JavaScript strings or arrays, Blobs are designed to efficiently handle large amounts of binary data. They're immutable, meaning once created, you can't change their contents. Instead, you create new Blobs from existing ones.
Unlike regular JavaScript strings or arrays, Blobs are designed to efficiently handle large amounts of binary data. As [MDN documents](https://developer.mozilla.org/en-US/docs/Web/API/Blob), they're immutable once created, you can't change their contents. Instead, you create new Blobs from existing ones.

```javascript
// Creating Blobs from different data types
Expand Down Expand Up @@ -1062,6 +1066,32 @@ document.addEventListener('paste', async (e) => {

---

## Frequently Asked Questions

<AccordionGroup>
<Accordion title="What is the difference between Blob and File in JavaScript?">
`File` extends `Blob` with metadata properties: `name`, `lastModified`, and `webkitRelativePath`. A File is always a Blob, but a Blob is not a File. File objects come from user input (`<input type="file">`) or drag-and-drop, while Blobs are created programmatically. The W3C File API specification defines this inheritance.
</Accordion>

<Accordion title="How do I create a downloadable file in JavaScript?">
Create a Blob with your content, generate an Object URL with `URL.createObjectURL(blob)`, assign it to an anchor element's `href`, set the `download` attribute to a filename, and trigger a click. Always call `URL.revokeObjectURL()` afterward to free memory.
</Accordion>

<Accordion title="What is the difference between Object URLs and Data URLs?">
Object URLs (`blob:...`) are references to in-memory Blob data — they're fast to create but must be manually revoked. Data URLs (`data:...`) encode the full content as a Base64 string — they're larger (about 33% overhead) but self-contained and can be saved or embedded. MDN recommends Object URLs for large files and temporary previews.
</Accordion>

<Accordion title="How do I read the contents of a user-selected file?">
Use the `FileReader` API or the modern `file.text()`, `file.arrayBuffer()`, and `file.stream()` methods. `FileReader` uses callbacks while the modern methods return Promises. For text files, `await file.text()` is the simplest approach. For binary data, use `await file.arrayBuffer()`.
</Accordion>

<Accordion title="How do I upload large files in chunks?">
Use `blob.slice(start, end)` to split a file into chunks, then upload each chunk separately with `fetch()` and `FormData`. This enables progress tracking, resumable uploads, and avoids server timeout limits. The W3C File API defines `slice()` as a method for creating sub-Blobs from ranges of the original data.
</Accordion>
</AccordionGroup>

---

## Related Concepts

<CardGroup cols={2}>
Expand Down
36 changes: 33 additions & 3 deletions docs/beyond/concepts/computed-property-names.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
title: "Computed Property Names in JS"
sidebarTitle: "Computed Property Names"
description: "Learn JavaScript computed property names. Create dynamic object keys with variables, expressions, Symbols, and computed methods for cleaner ES6+ code."
"og:type": "article"
"article:author": "Leonardo Maldonado"
"article:section": "Modern Syntax & Operators"
"article:tag": "computed property names, dynamic object keys, es6 syntax, bracket notation, symbols"
---

Have you ever needed to create an object where the property name comes from a variable? Before ES6, this required creating the object first, then adding the property in a separate step. Computed property names changed everything.
Expand All @@ -19,7 +23,7 @@ const obj2 = { [key2]: 'active' };
console.log(obj2); // { status: 'active' }
```

With **computed property names**, you can use any expression inside square brackets `[]` within an object literal, and JavaScript evaluates that expression to determine the property name. This seemingly small syntax addition enables powerful patterns for dynamic object creation.
With **computed property names**, introduced in the ECMAScript 2015 specification, you can use any expression inside square brackets `[]` within an object literal, and JavaScript evaluates that expression to determine the property name. This seemingly small syntax addition enables powerful patterns for dynamic object creation.

<Info>
**What you'll learn in this guide:**
Expand Down Expand Up @@ -279,7 +283,7 @@ console.log(defaults);

## Symbol Keys: The Primary Use Case

Symbols are unique, immutable identifiers that can **only** be used as object keys via computed property syntax. This is one of the most important use cases for computed properties.
Symbols are unique, immutable identifiers that can **only** be used as object keys via computed property syntax. According to MDN, this is one of the most important use cases for computed properties and the reason Symbols were designed alongside this syntax in ES2015.

### Why Symbols Need Computed Syntax

Expand Down Expand Up @@ -545,7 +549,7 @@ console.log(validated[Symbol.for('value')]); // 42

### Form Field Handling

React and Vue state updates commonly use computed properties:
React and Vue state updates commonly use computed properties. According to Stack Overflow's 2023 Developer Survey, React remains the most popular front-end framework, making this pattern one of the most widely used applications of computed property names:

```javascript
// React-style form handler
Expand Down Expand Up @@ -871,6 +875,32 @@ console.log(obj3.__proto__); // 'just a string' (own property)

---

## Frequently Asked Questions

<AccordionGroup>
<Accordion title="What are computed property names in JavaScript?">
Computed property names are an ES2015 feature that lets you use any expression inside square brackets `[]` in an object literal to dynamically determine a property's name at runtime. The expression is evaluated, converted to a string (or kept as a Symbol), and used as the key — all in a single expression.
</Accordion>

<Accordion title="How do you use a variable as an object key in JavaScript?">
Wrap the variable in square brackets inside the object literal: `{ [myVariable]: value }`. Without brackets, `{ myVariable: value }` creates a property literally named `"myVariable"`. The brackets tell JavaScript to evaluate the expression and use the result as the key name.
</Accordion>

<Accordion title="Why do Symbols require computed property syntax?">
Symbol values cannot be expressed as identifiers or string literals in object shorthand. Writing `{ mySymbol: value }` creates a string key `"mySymbol"`, not a Symbol key. Only the computed syntax `{ [mySymbol]: value }` evaluates the variable and uses the actual Symbol as the key, as specified in the ECMAScript standard.
</Accordion>

<Accordion title="What happens when two computed properties evaluate to the same key?">
The last one wins — JavaScript silently overwrites previous values with no error. This applies whether the duplicates come from computed properties, static properties, or a mix. MDN documents that this behavior is consistent with how all property assignments work in JavaScript.
</Accordion>

<Accordion title="Can I use computed property names with methods and getters/setters?">
Yes. Computed syntax works with method shorthand (`{ [name]() {} }`), generator methods (`{ *[name]() {} }`), async methods (`{ async [name]() {} }`), and accessor properties (`{ get [name]() {}, set [name](v) {} }`). This enables powerful patterns for dynamically-named APIs.
</Accordion>
</AccordionGroup>

---

## Related Concepts

<CardGroup cols={2}>
Expand Down
36 changes: 33 additions & 3 deletions docs/beyond/concepts/cookies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
title: "Cookies in JavaScript"
sidebarTitle: "Cookies"
description: "Learn JavaScript cookies. Understand how to read, write, and delete cookies, cookie attributes like HttpOnly and SameSite, and security best practices."
"og:type": "article"
"article:author": "Leonardo Maldonado"
"article:section": "Browser Storage"
"article:tag": "cookies, http cookies, cookie attributes, httponly samesite, cookie security"
---

Why do websites "remember" you're logged in, even after closing your browser? How does that shopping cart persist across tabs? Why can some data survive for weeks while other data vanishes when you close a tab?
Expand All @@ -17,7 +21,7 @@ console.log(document.cookie) // "username=Alice; theme=dark; lang=en"
// Cookie: username=Alice; theme=dark; lang=en
```

The answer is **cookies**. They're the original browser storage mechanism, and unlike localStorage, cookies are automatically sent to the server with every HTTP request. This makes them essential for authentication, sessions, and any data the server needs to know about.
The answer is **cookies**. Invented by Lou Montulli at Netscape in 1994, they're the original browser storage mechanism, and unlike localStorage, cookies are automatically sent to the server with every HTTP request. This makes them essential for authentication, sessions, and any data the server needs to know about.

<Info>
**What you'll learn in this guide:**
Expand Down Expand Up @@ -501,7 +505,7 @@ console.log(document.cookie) // sessionId won't appear

### SameSite: CSRF Protection

The [`SameSite`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#samesitesamesite-value) attribute controls when cookies are sent with cross-site requests:
The [`SameSite`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie#samesitesamesite-value) attribute controls when cookies are sent with cross-site requests. According to web.dev's SameSite cookies guide, Chrome changed the default from `None` to `Lax` in 2020, significantly improving CSRF protection across the web:

<Tabs>
<Tab title="Strict">
Expand Down Expand Up @@ -627,7 +631,7 @@ Cookies set by a different domain than the one you're visiting:

## Third-Party Cookie Deprecation

Major browsers are phasing out third-party cookies for privacy:
Major browsers are phasing out third-party cookies for privacy. According to MDN's third-party cookies documentation, this represents one of the most significant changes to web tracking since cookies were invented:

| Browser | Status |
|---------|--------|
Expand Down Expand Up @@ -961,6 +965,32 @@ With `Partitioned`, the cookie is isolated per top-level site:

---

## Frequently Asked Questions

<AccordionGroup>
<Accordion title="What is the difference between cookies and localStorage?">
Cookies are automatically sent to the server with every HTTP request and have a ~4KB size limit, while localStorage stays in the browser and offers ~5–10MB. Use cookies when the server needs the data (authentication, sessions). Use localStorage for client-only data like UI preferences that doesn't need to travel with requests.
</Accordion>

<Accordion title="What does the HttpOnly cookie attribute do?">
`HttpOnly` prevents JavaScript from accessing the cookie via `document.cookie`. This protects against XSS attacks — even if an attacker injects malicious JavaScript, they cannot steal HttpOnly cookies. According to MDN, HttpOnly can only be set by the server via the `Set-Cookie` header, not by client-side JavaScript.
</Accordion>

<Accordion title="What is the SameSite cookie attribute?">
`SameSite` controls whether cookies are sent with cross-site requests. `Strict` blocks all cross-site sending, `Lax` (the default since Chrome 80) allows cookies on top-level navigation but blocks them on cross-site POST requests, and `None` sends cookies on all requests but requires the `Secure` attribute.
</Accordion>

<Accordion title="How do you delete a cookie in JavaScript?">
Set the cookie with `max-age=0` or an `expires` date in the past using the same `path` and `domain` attributes as when it was originally set. There is no direct delete method — this is a common source of bugs when the path or domain doesn't match the original cookie.
</Accordion>

<Accordion title="Are third-party cookies being deprecated?">
Yes. Safari has blocked third-party cookies by default since 2020, Firefox blocks them in Enhanced Tracking Protection, and Chrome is rolling out restrictions through 2024–2025. According to MDN, partitioned cookies (CHIPS) provide an alternative for legitimate cross-site use cases like embedded widgets.
</Accordion>
</AccordionGroup>

---

## Related Concepts

<CardGroup cols={2}>
Expand Down
36 changes: 33 additions & 3 deletions docs/beyond/concepts/custom-events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
title: "Custom Events in JavaScript"
sidebarTitle: "Custom Events"
description: "Learn JavaScript custom events. Create and dispatch CustomEvent, pass data with detail, and build event-driven architectures."
"og:type": "article"
"article:author": "Leonardo Maldonado"
"article:section": "Events"
"article:tag": "custom events, customevent, event dispatch, event-driven architecture, event detail"
---

What if you could create your own events, just like `click` or `submit`? What if a shopping cart could announce "item added!" and any part of your app could listen and respond? How do you build components that communicate without knowing about each other?
Expand Down Expand Up @@ -41,7 +45,7 @@ The answer is **custom events**. They let you create your own event types, attac

## What is a Custom Event?

A **[custom event](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)** is a developer-defined event that you create, dispatch, and listen for in JavaScript. Unlike built-in events like `click` or `keydown` triggered by user actions, custom events are triggered programmatically using `dispatchEvent()`. The `CustomEvent` constructor extends the base `Event` interface, adding a `detail` property for passing data to listeners.
A **[custom event](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent)** is a developer-defined event that you create, dispatch, and listen for in JavaScript. Unlike built-in events like `click` or `keydown` triggered by user actions, custom events are triggered programmatically using `dispatchEvent()`. The `CustomEvent` constructor extends the base `Event` interface, adding a `detail` property for passing data to listeners. [Can I Use data](https://caniuse.com/customevent) shows the `CustomEvent` constructor is supported in over 98% of browsers globally.

<Note>
Custom events work with any [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), including DOM elements, the `document`, `window`, and even custom objects that extend `EventTarget`.
Expand Down Expand Up @@ -89,7 +93,7 @@ Think of custom events like a radio broadcast:
└─────────────────────────────────────────────────────────────────────────────┘
```

This decoupling is the superpower of custom events. Components can communicate without importing each other or knowing each other exists.
This decoupling is the superpower of custom events. As MDN's guide on [creating and triggering events](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events) explains, this pub/sub pattern lets components communicate without importing each other or knowing each other exists.

---

Expand Down Expand Up @@ -261,7 +265,7 @@ someElement.dispatchEvent(event)

### Important: dispatchEvent is Synchronous

Unlike native browser events (which are processed asynchronously through the event loop), `dispatchEvent()` is **synchronous**. All listeners execute immediately before `dispatchEvent()` returns:
Unlike native browser events (which are processed asynchronously through the event loop), `dispatchEvent()` is **synchronous**. As the [W3C DOM specification](https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent) states, dispatching is a synchronous operation — all listeners execute immediately before `dispatchEvent()` returns:

```javascript
console.log('1: Before dispatch')
Expand Down Expand Up @@ -837,6 +841,32 @@ button.dispatchEvent(new CustomEvent('customClick'))

---

## Frequently Asked Questions

<AccordionGroup>
<Accordion title="How do I create a custom event in JavaScript?">
Use the `CustomEvent` constructor: `new CustomEvent('eventName', { detail: data })`. The `detail` property can hold any JavaScript value — objects, arrays, or primitives. Then dispatch it on any element with `element.dispatchEvent(event)`.
</Accordion>

<Accordion title="Do custom events bubble like native events?">
No — custom events do not bubble by default. You must explicitly set `bubbles: true` in the options object to enable bubbling. Without it, only listeners directly on the dispatching element will receive the event, as documented in the W3C DOM specification.
</Accordion>

<Accordion title="What is the difference between Event and CustomEvent?">
`CustomEvent` extends `Event` with one key addition: the `detail` property for passing arbitrary data. If you don't need to send data to listeners, `new Event('name')` works fine. MDN recommends `CustomEvent` when you need to communicate data alongside the event.
</Accordion>

<Accordion title="Is dispatchEvent synchronous or asynchronous?">
`dispatchEvent()` is synchronous — all listeners execute immediately before the method returns. This differs from native browser events, which are processed asynchronously through the event loop. You can use the return value of `dispatchEvent()` to check if any listener called `preventDefault()`.
</Accordion>

<Accordion title="Can I use onclick-style properties for custom events?">
No. Custom events do not have corresponding `on*` properties like native events. `element.onmyEvent = handler` does nothing — you must use `addEventListener()` to listen for custom events. This is a common mistake MDN specifically warns about.
</Accordion>
</AccordionGroup>

---

## Related Concepts

<CardGroup cols={2}>
Expand Down
Loading