Missed Part 1? [Read it here] — covers
structuredClone,Object.groupBy,AbortController,Promise.any, and more.
🧩 More Modern APIs You Should Already Be Using
1. Object.hasOwn()
❌ Old way
if (obj.hasOwnProperty("key")) { ... }
⚠️ Why this is dangerous
-
hasOwnPropertycan be overridden on the object itself - Breaks completely on
null-prototype objects (e.g.Object.create(null))
const obj = Object.create(null);
obj.name = "Nagendra";
obj.hasOwnProperty("name"); // ❌ TypeError: obj.hasOwnProperty is not a function
// Also risky:
const user = {
hasOwnProperty: () => true, // someone overrides it
};
user.hasOwnProperty("anything"); // true ❌ — lies to you
✅ Modern way
Object.hasOwn(obj, "key");
🧠 Real-world use cases
// Safe check on any object
const config = Object.create(null); // null-prototype object
config.theme = "dark";
Object.hasOwn(config, "theme"); // true ✅
Object.hasOwn(config, "version"); // false ✅
// Filtering only own properties (not inherited)
const base = { type: "admin" };
const user = Object.create(base);
user.name = "Nagendra";
user.age = 28;
Object.keys(user).filter(key => Object.hasOwn(user, key));
// ["name", "age"] — excludes inherited "type" ✅
// Safe API response validation
function hasField(response, field) {
return Object.hasOwn(response, field);
}
if (hasField(apiResponse, "data")) {
render(apiResponse.data);
}
2. Immutable Sorting — .toSorted()
❌ Old way
const sorted = [...arr].sort(); // spread just to avoid mutation
arr.sort(); // mutates original ❌
✅ Modern way
const sorted = arr.toSorted();
// original arr is untouched ✅
🧠 Real-world use cases
const players = [
{ name: "Arjun", score: 450 },
{ name: "Priya", score: 820 },
{ name: "Rahul", score: 610 },
];
// Sort without touching the original
const leaderboard = players.toSorted((a, b) => b.score - a.score);
console.log(leaderboard[0].name); // "Priya" ✅
console.log(players[0].name); // "Arjun" — original unchanged ✅
// Great in React — no accidental state mutation
const [items, setItems] = useState(initialItems);
const handleSort = () => {
// safe — doesn't mutate state directly
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));
setItems(sorted);
};
// Also available: .toReversed()
const original = [1, 2, 3, 4, 5];
const reversed = original.toReversed();
console.log(reversed); // [5, 4, 3, 2, 1]
console.log(original); // [1, 2, 3, 4, 5] — untouched ✅
3. Update Array Without Mutation — .with()
❌ Old way
// Spread + map just to update one index
const updated = arr.map((item, i) => i === 2 ? "new value" : item);
// Or splice — mutates ❌
const copy = [...arr];
copy.splice(2, 1, "new value");
✅ Modern way
const updated = arr.with(2, "new value");
// original arr untouched ✅
🧠 Real-world use cases
const seats = ["A1", "A2", "A3", "A4", "A5"];
// Book seat at index 2
const booked = seats.with(2, "BOOKED");
console.log(booked); // ["A1", "A2", "BOOKED", "A4", "A5"]
console.log(seats); // ["A1", "A2", "A3", "A4", "A5"] — original safe ✅
// React state update — clean and immutable
const [cart, setCart] = useState(initialCart);
const updateQuantity = (index, qty) => {
setCart(prev => prev.with(index, { ...prev[index], quantity: qty }));
};
// Negative index works too
const arr = [10, 20, 30, 40, 50];
arr.with(-1, 99); // [10, 20, 30, 40, 99] — updates last item
arr.with(-2, 88); // [10, 20, 30, 88, 50] — updates second to last
4. Find Last Matching Item — .findLast()
❌ Old way
// Reverse + find — mutates or wastes memory
const last = [...arr].reverse().find(x => x.status === "error");
// Or filter + at(-1)
const last = arr.filter(x => x.status === "error").at(-1);
// creates a whole new filtered array just for one item ❌
✅ Modern way
const last = arr.findLast(x => x.status === "error");
🧠 Real-world use cases
const logs = [
{ id: 1, status: "success", msg: "User logged in" },
{ id: 2, status: "error", msg: "DB timeout" },
{ id: 3, status: "success", msg: "Data fetched" },
{ id: 4, status: "error", msg: "API failed" },
{ id: 5, status: "success", msg: "Response sent" },
];
// Get the most recent error
const lastError = logs.findLast(log => log.status === "error");
console.log(lastError.msg); // "API failed" ✅
// Get index of most recent error
const lastErrorIndex = logs.findLastIndex(log => log.status === "error");
console.log(lastErrorIndex); // 3 ✅
// Chat app — find last unread message
const lastUnread = messages.findLast(m => !m.read);
// Version history — find last auto-save
const lastAutoSave = history.findLast(h => h.type === "autosave");
// Transaction log — find last failed payment
const lastFailed = transactions.findLast(t => t.status === "failed");
5. URLSearchParams
❌ Old way — manual string parsing
// Fragile, breaks with encoding, edge cases everywhere
const query = window.location.search.slice(1); // remove "?"
const params = {};
query.split("&").forEach(pair => {
const [key, val] = pair.split("=");
params[decodeURIComponent(key)] = decodeURIComponent(val);
});
✅ Modern way
const params = new URLSearchParams(window.location.search);
params.get("page"); // "2"
🧠 Real-world use cases
// URL: /products?category=shoes&sort=price&page=2
const params = new URLSearchParams(window.location.search);
params.get("category"); // "shoes"
params.get("sort"); // "price"
params.get("page"); // "2"
params.get("missing"); // null — no crash ✅
params.has("sort"); // true
// Build query strings for API calls
const filters = new URLSearchParams({
category: "electronics",
minPrice: 500,
maxPrice: 50000,
inStock: true,
});
fetch(`/api/products?${filters.toString()}`);
// /api/products?category=electronics&minPrice=500&maxPrice=50000&inStock=true
// Update URL without page reload (React / SPA)
const params = new URLSearchParams(window.location.search);
params.set("page", 3);
params.delete("sort");
window.history.pushState({}, "", `?${params.toString()}`);
// Handle multi-value params
// URL: /filter?tag=js&tag=react&tag=css
const params = new URLSearchParams(window.location.search);
params.getAll("tag"); // ["js", "react", "css"] ✅
6. Generate IDs — crypto.randomUUID()
❌ Old way — installing a package
// npm install uuid ← unnecessary dependency
import { v4 as uuidv4 } from "uuid";
const id = uuidv4(); // "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
✅ Modern way — built-in, zero install
const id = crypto.randomUUID();
// "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d" ✅
🧠 Real-world use cases
// Generate unique IDs for new items
const newTodo = {
id: crypto.randomUUID(),
text: "Learn modern JS",
completed: false,
createdAt: new Date(),
};
// React — stable keys for dynamic lists
const addItem = (text) => {
setItems(prev => [
...prev,
{ id: crypto.randomUUID(), text, done: false }
]);
};
return items.map(item => (
<TodoItem key={item.id} item={item} /> // ✅ stable unique key
));
// Session / request tracking
const requestId = crypto.randomUUID();
fetch("/api/data", {
headers: { "X-Request-ID": requestId }
});
// File upload naming
const ext = file.name.split(".").at(-1);
const filename = `${crypto.randomUUID()}.${ext}`;
// "3f2504e0-4f89-11d3-9a0c-0305e82c3301.png"
✅ Available in all modern browsers and Node.js 14.17+
✅ Cryptographically secure — notMath.random()
❌ Uninstall theuuidpackage — you don't need it anymore
🔁 Quick Reference Table
| Old Pattern | Modern Replacement | Why Better |
|---|---|---|
obj.hasOwnProperty("key") |
Object.hasOwn(obj, "key") |
Safe on null-prototype objects, can't be overridden |
[...arr].sort() |
arr.toSorted() |
No spread needed, original untouched |
arr.reverse() |
arr.toReversed() |
Non-mutating version |
arr.map() / splice to update index |
arr.with(index, value) |
One-liner, immutable |
[...arr].reverse().find() |
arr.findLast() |
No copy, reads from end directly |
Manual split("&") query parsing |
URLSearchParams |
Handles encoding, multi-values, edge cases |
npm install uuid |
crypto.randomUUID() |
Built-in, cryptographically secure, zero deps |
📚 Want to Go Deeper?
If you want to master modern JavaScript and web development from scratch to production, check out:
👉 Modern Web Course — jsden.com/courses/modern-web
You'll go beyond tips and actually build things the right way with modern APIs, patterns, and real-world projects.
🎯 Final Thoughts
Modern JavaScript keeps getting better — and most of it ships in the browser with zero install.
👉 Delete unnecessary npm packages
👉 Use Object.hasOwn() over hasOwnProperty
👉 Embrace immutable array methods — your React app will thank you
👉 crypto.randomUUID() and URLSearchParams are already on your machine
Missed Part 1? [Read it here] — covers structuredClone, Object.groupBy, AbortController, CSS :has(), Promise.any, and Intl.
Which of these were you still doing the old way? Drop it in the comments 👇

Top comments (0)