
- Javascript Basics Tutorial
- Javascript - Home
- JavaScript - Roadmap
- JavaScript - Overview
- JavaScript - Features
- JavaScript - Enabling
- JavaScript - Placement
- JavaScript - Syntax
- JavaScript - Hello World
- JavaScript - Console.log()
- JavaScript - Comments
- JavaScript - Variables
- JavaScript - let Statement
- JavaScript - Constants
- JavaScript - Data Types
- JavaScript - Type Conversions
- JavaScript - Strict Mode
- JavaScript - Reserved Keywords
- JavaScript Operators
- JavaScript - Operators
- JavaScript - Arithmetic Operators
- JavaScript - Comparison Operators
- JavaScript - Logical Operators
- JavaScript - Bitwise Operators
- JavaScript - Assignment Operators
- JavaScript - Conditional Operators
- JavaScript - typeof Operator
- JavaScript - Nullish Coalescing Operator
- JavaScript - Safe Assignment Operator
- JavaScript - Delete Operator
- JavaScript - Comma Operator
- JavaScript - Grouping Operator
- JavaScript - Yield Operator
- JavaScript - Spread Operator
- JavaScript - Exponentiation Operator
- JavaScript - Operator Precedence
- JavaScript Control Flow
- JavaScript - If...Else
- JavaScript - While Loop
- JavaScript - For Loop
- JavaScript - For...in
- Javascript - For...of
- JavaScript - Loop Control
- JavaScript - Break Statement
- JavaScript - Continue Statement
- JavaScript - Switch Case
- JavaScript - User Defined Iterators
- JavaScript Functions
- JavaScript - Functions
- JavaScript - Function Expressions
- JavaScript - Function Parameters
- JavaScript - Default Parameters
- JavaScript - Function() Constructor
- JavaScript - Function Hoisting
- JavaScript - Self-Invoking Functions
- JavaScript - Arrow Functions
- JavaScript - Function Invocation
- JavaScript - Function call()
- JavaScript - Function apply()
- JavaScript - Function bind()
- JavaScript - Closures
- JavaScript - Variable Scope
- JavaScript - Global Variables
- JavaScript - Smart Function Parameters
- JavaScript Objects
- JavaScript - Number
- JavaScript - Boolean
- JavaScript - Strings
- JavaScript - Arrays
- JavaScript - Date
- JavaScript - DataView
- JavaScript - Handler
- JavaScript - Math
- JavaScript - RegExp
- JavaScript - Symbol
- JavaScript - Sets
- JavaScript - WeakSet
- JavaScript - Maps
- JavaScript - WeakMap
- JavaScript - Iterables
- JavaScript - Reflect
- JavaScript - TypedArray
- JavaScript - Template Literals
- JavaScript - Tagged Templates
- Object Oriented JavaScript
- JavaScript - Objects
- JavaScript - Classes
- JavaScript - Object Properties
- JavaScript - Object Methods
- JavaScript - Static Methods
- JavaScript - Display Objects
- JavaScript - Object Accessors
- JavaScript - Object Constructors
- JavaScript - Native Prototypes
- JavaScript - ES5 Object Methods
- JavaScript - Encapsulation
- JavaScript - Inheritance
- JavaScript - Abstraction
- JavaScript - Polymorphism
- JavaScript - Destructuring
- JavaScript - Destructuring Assignment
- JavaScript - Object Destructuring
- JavaScript - Array Destructuring
- JavaScript - Nested Destructuring
- JavaScript - Optional Chaining
- JavaScript - Global Object
- JavaScript - Mixins
- JavaScript - Proxies
- JavaScript Versions
- JavaScript - History
- JavaScript - Versions
- JavaScript - ES5
- JavaScript - ES6
- ECMAScript 2016
- ECMAScript 2017
- ECMAScript 2018
- ECMAScript 2019
- ECMAScript 2020
- ECMAScript 2021
- ECMAScript 2022
- JavaScript Asynchronous
- JavaScript - Asynchronous
- JavaScript - Callback Functions
- JavaScript - Promises
- JavaScript - Async/Await
- JavaScript - Microtasks
- JavaScript - Promisification
- JavaScript - Promises Chaining
- JavaScript - Timing Events
- JavaScript - setTimeout()
- JavaScript - setInterval()
- JavaScript Cookies
- JavaScript - Cookies
- JavaScript - Cookie Attributes
- JavaScript - Deleting Cookies
- JavaScript Browser BOM
- JavaScript - Browser Object Model
- JavaScript - Window Object
- JavaScript - Document Object
- JavaScript - Screen Object
- JavaScript - History Object
- JavaScript - Navigator Object
- JavaScript - Location Object
- JavaScript - Console Object
- JavaScript Web APIs
- JavaScript - Web API
- JavaScript - History API
- JavaScript - Storage API
- JavaScript - Forms API
- JavaScript - Worker API
- JavaScript - Fetch API
- JavaScript - Geolocation API
- JavaScript Events
- JavaScript - Events
- JavaScript - DOM Events
- JavaScript - addEventListener()
- JavaScript - Mouse Events
- JavaScript - Keyboard Events
- JavaScript - Form Events
- JavaScript - Window/Document Events
- JavaScript - Event Delegation
- JavaScript - Event Bubbling
- JavaScript - Event Capturing
- JavaScript - Custom Events
- JavaScript Error Handling
- JavaScript - Error Handling
- JavaScript - try...catch
- JavaScript - Debugging
- JavaScript - Custom Errors
- JavaScript - Extending Errors
- JavaScript Important Keywords
- JavaScript - this Keyword
- JavaScript - void Keyword
- JavaScript - new Keyword
- JavaScript - var Keyword
- JavaScript HTML DOM
- JavaScript - HTML DOM
- JavaScript - DOM Methods & Properties
- JavaScript - DOM Document
- JavaScript - DOM Elements
- JavaScript - DOM Attributes (Attr)
- JavaScript - DOM Forms
- JavaScript - Changing HTML
- JavaScript - Changing CSS
- JavaScript - DOM Animation
- JavaScript - DOM Navigation
- JavaScript - DOM Collections
- JavaScript - DOM NodeList
- JavaScript - DOM DOMTokenList
- JavaScript Advanced Chapters
- JavaScript - Bubble Sort Algorithm
- JavaScript - Circular Reference Error
- JavaScript - Code Testing with Jest
- JavaScript - CORS Handling
- JavaScript - Data Analysis
- JavaScript - Dead Zone
- JavaScript - Design Patterns
- JavaScript - Engine and Runtime
- JavaScript - Execution Context
- JavaScript - Function Composition
- JavaScript - Immutability
- JavaScript - Kaboom.js
- JavaScript - Lexical Scope
- JavaScript - Local Storage
- JavaScript - Memoization
- JavaScript - Minifying JS
- JavaScript - Mutability vs Immutability
- JavaScript - Package Manager
- JavaScript - Parse S-Expressions
- JavaScript - Prototypal Inheritance
- JavaScript - Reactivity
- JavaScript - Require Function
- JavaScript - Selection API
- JavaScript - Session Storage
- JavaScript - SQL CRUD Operations
- JavaScript - Supercharged Sorts
- JavaScript - Temporal Dead Zone
- JavaScript - Throttling
- JavaScript - TRPC Library
- JavaScript - Truthy and Falsy Values
- JavaScript - Upload Files
- JavaScript - Date Comparison
- JavaScript - Recursion
- JavaScript - Data Structures
- JavaScript - Base64 Encoding
- JavaScript - Callback Function
- JavaScript - Current Date/Time
- JavaScript - Date Validation
- JavaScript - Filter Method
- JavaScript - Generating Colors
- JavaScript - HTTP Requests
- JavaScript - Insertion Sort
- JavaScript - Lazy Loading
- JavaScript - Linked List
- JavaScript - Nested Loop
- JavaScript - Null Checking
- JavaScript - Get Current URL
- JavaScript - Graph Algorithms
- JavaScript - Higher Order Functions
- JavaScript - Empty String Check
- JavaScript - Form Handling
- JavaScript - Functional Programming
- JavaScript - Parameters vs Arguments
- JavaScript - Prototype
- JavaScript - Reactive Programming
- JavaScript - Reduce Method
- JavaScript - Rest Operator
- JavaScript - Short Circuiting
- JavaScript - Undefined Check
- JavaScript - Unit Testing
- JavaScript - Validate URL
- JavaScript Miscellaneous
- JavaScript - Ajax
- JavaScript - Async Iteration
- JavaScript - Atomics Objects
- JavaScript - Rest Parameter
- JavaScript - Page Redirect
- JavaScript - Dialog Boxes
- JavaScript - Page Printing
- JavaScript - Validations
- JavaScript - Animation
- JavaScript - Multimedia
- JavaScript - Image Map
- JavaScript - Browsers
- JavaScript - JSON
- JavaScript - Multiline Strings
- JavaScript - Date Formats
- JavaScript - Get Date Methods
- JavaScript - Set Date Methods
- JavaScript - Modules
- JavaScript - Dynamic Imports
- JavaScript - BigInt
- JavaScript - Blob
- JavaScript - Unicode
- JavaScript - Shallow Copy
- JavaScript - Call Stack
- JavaScript - Reference Type
- JavaScript - IndexedDB
- JavaScript - Clickjacking Attack
- JavaScript - Currying
- JavaScript - Graphics
- JavaScript - Canvas
- JavaScript - Debouncing
- JavaScript - Performance
- JavaScript - Style Guide
JavaScript - Reactivity
In web development responsiveness refers to how a system responds to changes in data. This concept is important for creating modern, dynamic web applications in which user actions need speedy responses like updating a page without reloading it or dynamically changing what the user sees when data is updated.
This chapter covers some powerful JavaScript patterns that can help you build reactive systems. These patterns are commonly used in frameworks like React and Vue but understanding them in simple JavaScript allows you to understand the fundamental concepts.
Why use Reactivity?
Web apps today are highly interactive. When users click buttons, navigate pages or enter data so the application must reply quickly and change what shows on the screen. Addressing such updates manually can be difficult, but reactivity makes it easier by automatically responding to changes in data.
Key Reactivity Patterns in JavaScript
Now we will explore some key reactivity patterns in JavaScript in this section. These patterns allow us to react rapidly to changes in data and how the page responds to user actions. They are used in many popular libraries and frameworks but we will show how to use them in simple JavaScript.
Pub/Sub: Simplified Data Flow Management
The Pub/Sub (Publisher/Subscriber) pattern is a common approach to manage data flows. It differentiates between code that changes data (publisher) and code that responds to those updates (subscriber). This makes it easy to manage the various parts of an app separately.
Example
Following is the simple demonstration of this Reactivity Pattern −
class PS { constructor() { this.t = {}; // Tracks events and subscribers } sub(tp, cb) { if (!this.t[tp]) { this.t[tp] = []; } this.t[tp].push(cb); } pub(tp, d) { if (this.t[tp]) { this.t[tp].forEach((cb) => cb(d)); } } } const ps = new PS(); ps.sub('n', (msg) => console.log(`News: ${msg}`)); ps.pub('n', 'New update available!');
This method is used in systems like Redux in which components notice changes and update accordingly.
Output
This will generate the below result −
News: New update available!
Custom Events: Browser-Built Pub/Sub for Reactivity
The browser provides an API for triggering and subscribing to custom events using the CustomEvent class and dispatchEvent method. The latter allows us to not only create an event, but also attach any needed data to it.
Example
Below is a simple example of this reactivity pattern −
const evt = new CustomEvent('cEvt', { detail: 'Event data', }); const el = document.getElementById('target'); el.addEventListener('cEvt', (e) => console.log(`Event: ${e.detail}`)); el.dispatchEvent(evt);
This technique is appropriate for simple event triggering without the need of libraries.
Output
This will give the following outcome −
Event: Event data
Custom Event Targets
If you do not wish to dispatch events globally on the window object, you can create your own event target.
By modifying the native EventTarget class you can transmit events to a new instance. This makes sure your events are only triggered for the new class which prevents global propagation. Also you can connect handlers directly to this instance.
Example
The following code shows a simple use of this reactivity pattern −
class CET extends EventTarget { trig(evtName, evtData) { const evt = new CustomEvent(evtName, { detail: evtData }); this.dispatchEvent(evt); } } const ct = new CET(); ct.addEventListener('cEvt', (e) => console.log(`Event: ${e.detail}`)); ct.trig('cEvt', 'Hello from event!');
Output
This will create the below outcome −
Event: Hello from event!
Observer Pattern: Flexible Updates for Decoupled Code
The Observer pattern is very similar to PubSub. You can subscribe to the Subject, which informs its subscribers (Observers) of changes and allows them to reply accordingly. This method is important for designing a disconnected and flexible architecture.
Example
Here's a basic demonstration of how this reactivity pattern works −
class Sub { constructor() { this.obs = []; } sub(o) { this.obs.push(o); } notify(d) { this.obs.forEach((o) => o.up(d)); } } class Obs { constructor(n) { this.n = n; } up(d) { console.log(`${this.n} got: ${d}`); } } const s = new Sub(); const o1 = new Obs('Obs 1'); s.sub(o1); s.notify('New info!');
Output
This will create the below outcome −
Obs 1 got: New info!
Reactive Properties with Proxy
The Proxy object lets you intercept property access actions (get and set) within objects. This enables you to create reactivity and run code whenever a property's value is retrieved or updated.
Example
This is a simple example showing the reactivity pattern in action −
let d = { n: 'Akash', a: 25 }; let rData = new Proxy(d, { get(t, p) { console.log(`Read: "${p}" = ${t[p]}`); return t[p]; }, set(t, p, v) { console.log(`Changed: "${p}" from ${t[p]} to ${v}`); t[p] = v; return true; } }); rData.n = 'Vikas';
Output
This will lead to the following outcome −
Changed: "n" from Akash to Vikas
Individual Property Reactivity
If you don't need to keep track of all an object's fields you can use Object.defineProperty to select one or Object.defineProperties to group them together.
Example
The code below provides a clear demonstration of this reactivity pattern −
let u = { _n: 'Akash' }; Object.defineProperty(u, 'n', { get() { return this._n; }, set(v) { console.log(`Name changed from ${this._n} to ${v}`); this._n = v; } }); u.n = 'Vikas';
Output
This will produce the following result −
Name changed from Akash to Vikas
Reactive HTML Attributes with MutationObserver
MutationObserver is a JavaScript API that monitors changes to the DOM (Document Object Model) like attribute changes, element additions or deletions etc. It is particularly applicable for running code in response to DOM changes without having to actively monitor them.
Example
Here is a simple implementation of this particular reactivity pattern −
const el = document.getElementById('obs-el'); const obs = new MutationObserver((muts) => { muts.forEach(m => { if (m.attributeName === 'class') { console.log('Class changed!'); } }); }); obs.observe(el, { attributes: true });
Output
This will generate the below result −
Class changed!
Reactive Scrolling with IntersectionObserver
The IntersectionObserver API allows you to asynchronously monitor changes in the intersection of a target element with an ancestor element or the viewport of a top-level document. This means you can execute code anytime an element enters or quits the viewport or another specific element.
This is particularly useful for lazy image loading, infinite scrolling, scroll position-based animations, and other features.
Example
Below is an example of this reactivity pattern −
// Function to be called when the observed element is intersecting function onIntersect(entries, obs) { entries.forEach(e => { e.target.style.backgroundColor = e.isIntersecting ? 'lightgreen' : 'grey'; }); } // Create an IntersectionObserver with the callback const obs = new IntersectionObserver(onIntersect); // Start observing an element const el = document.getElementById('spec-el'); obs.observe(el);
Output
Below is the output when the element enters the viewport −
Element is now in view.
This will be the output when the element exits the viewport −
Element is now out of view.