JavaScript arrays are powerful—but they don’t emit events . Want to react when someone .push()es a new item? You’re out of luck... unless you take control.
This post shows you how to intercept array mutations and dispatch custom events when push() is called — all in vanilla JavaScript, no frameworks, no proxies.
We want to monitor this:
myArray.push("newItem");
And react like this:
document.addEventListener("arrayPush", e => { console.log("Pushed:", e.detail); });
function createObservableArray(initial = []) { const arr = [...initial]; arr.push = function (...items) { const result = Array.prototype.push.apply(this, items); const event = new CustomEvent("arrayPush", { detail: { added: items, newLength: this.length } }); document.dispatchEvent(event); return result; }; return arr; }
const myArray = createObservableArray(); document.addEventListener("arrayPush", (e) => { console.log("Array was pushed:", e.detail); }); myArray.push("alpha"); // logs: { added: ["alpha"], newLength: 1 } myArray.push("beta", "gamma"); // logs: { added: ["beta", "gamma"], newLength: 3 }
push() on a per-array basisArray.prototype.push.apply(...)CustomEvent with rich detailWant to observe pop, shift, or even splice? Here’s a sketch:
function makeObservable(arr, methods = ["push"]) { for (const method of methods) { const original = arr[method]; arr[method] = function (...args) { const result = original.apply(this, args); document.dispatchEvent(new CustomEvent(`array:${method}`, { detail: { args, result, current: [...this] } })); return result; }; } return arr; }
const list = makeObservable([]); document.addEventListener("array:push", e => console.log("Pushed", e.detail)); document.addEventListener("array:pop", e => console.log("Popped", e.detail)); list.push("x"); list.pop();
Want a more general-purpose reactive array? Use a Proxy. It’s more powerful but less performant:
function reactiveArray(arr = []) { return new Proxy(arr, { get(target, prop) { if (prop === "push") { return (...items) => { const result = Array.prototype.push.apply(target, items); document.dispatchEvent(new CustomEvent("arrayPush", { detail: { added: items } })); return result; }; } return Reflect.get(target, prop); } }); }
You don’t need Vue or MobX to detect array changes. With just a few lines of JavaScript, you can:
This pattern is a foundation for reactive state systems, event-driven logic, or any scenario where "changes should trigger actions."
Want a React-compatible or Svelte-integrated version? Ask and I'll tailor one.
Test your understanding with 3 quick questions