20 JavaScript Tricks Every Developer Must Know

Learn 20 practical JavaScript tips and tricks with real code examples for cleaner, faster, and more reliable code.

Soman Bandesha Updated 21 min read
20 JavaScript Tricks Every Developer Must Know

20 JavaScript tricks every developer must know

JavaScript is easy to start and surprisingly easy to write badly.

You can build a working feature with basic variables, loops, functions, and if statements. But once the project grows, small habits start to matter. How you handle missing API data, clone objects, remove duplicates, cancel requests, or format numbers can make your code either calm or annoying to maintain.

This guide covers 20 JavaScript tips and tricks every developer should know. Some are beginner friendly. Some are advanced JavaScript techniques. All of them are practical.

No weird one-liners just to look clever. No “hacks” that make your teammates hate you. Just useful JavaScript code examples you can actually use.

Quick overview

TrickBest for
Optional chainingReading nested data safely
Nullish coalescingSetting better fallback values
DestructuringPulling values from objects and arrays
Renaming while destructuringCleaning up API field names
Spread syntaxCopying and merging data
Rest parametersAccepting flexible arguments
SetRemoving duplicate values
MapStoring key-value data cleanly
Array.from()Creating arrays from iterables
flatMap()Mapping and flattening together
Object.hasOwn()Checking object properties safely
structuredClone()Deep cloning data
Promise.all()Running async tasks in parallel
Promise.allSettled()Handling partial async failures
AbortControllerCanceling fetch requests
URLSearchParamsWorking with query strings
Intl.NumberFormatFormatting money and numbers
Dynamic importsLoading code only when needed
Guard clausesMaking functions easier to read
DebounceLimiting frequent function calls

1. Use optional chaining for safer nested data

APIs rarely return perfect data. A user may not have a profile. A profile may not have an address. An address may not have a city.

Without optional chaining, you often end up with code like this:

const city =
  user &&
  user.profile &&
  user.profile.address &&
  user.profile.address.city;

It works, but it is hard to read.

Use optional chaining instead:

const city = user?.profile?.address?.city;

If any part of the chain is null or undefined, JavaScript returns undefined instead of throwing an error.

A more realistic example:

function getCustomerCity(order) {
  return order?.customer?.shippingAddress?.city;
}

console.log(getCustomerCity({})); 
// undefined

This is one of the simplest JavaScript tips and tricks for beginners, but experienced developers use it every day.

When to use it

Use optional chaining when you are reading data that may not exist:

const avatar = user?.profile?.avatarUrl;
const firstItemName = order?.items?.[0]?.name;
const callbackResult = options?.onSuccess?.();

Common mistake

Do not use optional chaining to hide bad assumptions.

// This may hide a real bug
const price = product?.price;

If every product must have a price, let the error happen or validate the data earlier. Optional chaining is for truly optional data, not broken data.

2. Use ?? instead of || for better defaults

Many developers use || to set default values:

const quantity = inputQuantity || 1;

That looks fine until inputQuantity is 0.

const inputQuantity = 0;
const quantity = inputQuantity || 1;

console.log(quantity);
// 1

The value 0 is valid, but JavaScript treats it as falsy.

Use nullish coalescing instead:

const quantity = inputQuantity ?? 1;

console.log(quantity);
// 0

The ?? operator only falls back when the left side is null or undefined.

const username = "";
const displayName = username ?? "Anonymous";

console.log(displayName);
// ""

That is usually what you want when setting defaults.

Good use cases

const page = query.page ?? 1;
const limit = query.limit ?? 20;
const theme = user.settings?.theme ?? "light";
const showSidebar = user.preferences?.showSidebar ?? true;

|| vs ??

| Value | value || "default" | value ?? "default" | |---|---|---| | 0 | "default" | 0 | | "" | "default" | "" | | false | "default" | false | | null | "default" | "default" | | undefined | "default" | "default" |

Use ?? when empty strings, zero, or false are valid values.

3. Destructure objects to reduce repeated code

Instead of writing the object name again and again:

function showUser(user) {
  console.log(user.name);
  console.log(user.email);
  console.log(user.role);
}

Use destructuring:

function showUser(user) {
  const { name, email, role } = user;

  console.log(name);
  console.log(email);
  console.log(role);
}

You can also destructure directly in function parameters:

function showUser({ name, email, role }) {
  return `${name} (${role}) - ${email}`;
}

That is cleaner when the function only needs a few fields.

Destructuring with default values

function createUser({ name, role = "member" }) {
  return {
    name,
    role
  };
}

console.log(createUser({ name: "Ani" }));
// { name: "Ani", role: "member" }

This is useful for options objects:

function createButton({
  label,
  variant = "primary",
  disabled = false
}) {
  return {
    label,
    variant,
    disabled
  };
}

Array destructuring

const coordinates = [40.1772, 44.5035];

const [latitude, longitude] = coordinates;

console.log(latitude);
// 40.1772

You can skip values too:

const colors = ["red", "green", "blue"];

const [firstColor, , thirdColor] = colors;

console.log(firstColor);
// red

console.log(thirdColor);
// blue

4. Rename variables while destructuring

APIs often use naming styles that do not match your code.

Example:

const response = {
  user_id: 42,
  first_name: "Narek",
  account_status: "active"
};

You can rename fields while destructuring:

const {
  user_id: userId,
  first_name: firstName,
  account_status: accountStatus
} = response;

console.log(userId);
// 42

This keeps your internal code readable without changing the API response.

With default values

const settings = {
  theme_mode: "dark"
};

const {
  theme_mode: themeMode = "light"
} = settings;

console.log(themeMode);
// dark

Nested rename example

const order = {
  customer: {
    full_name: "Mariam Hakobyan"
  }
};

const {
  customer: {
    full_name: customerName
  }
} = order;

console.log(customerName);
// Mariam Hakobyan

Be careful with deeply nested destructuring. It can get unreadable fast. If it starts looking like a puzzle, split it into smaller steps.

5. Use spread syntax to copy and merge data

Spread syntax is one of the most used JavaScript tricks because it works with both arrays and objects.

Copy an array

const numbers = [1, 2, 3];

const copy = [...numbers];

console.log(copy);
// [1, 2, 3]

Merge arrays

const frontend = ["HTML", "CSS"];
const scripting = ["JavaScript", "TypeScript"];

const skills = [...frontend, ...scripting];

console.log(skills);
// ["HTML", "CSS", "JavaScript", "TypeScript"]

Copy an object

const user = {
  name: "Aram",
  role: "editor"
};

const copiedUser = { ...user };

Merge objects

const defaults = {
  theme: "light",
  notifications: true
};

const userSettings = {
  theme: "dark"
};

const settings = {
  ...defaults,
  ...userSettings
};

console.log(settings);
// { theme: "dark", notifications: true }

Order matters. Later properties overwrite earlier properties.

Common mistake: spread is shallow

const original = {
  profile: {
    name: "Ani"
  }
};

const copy = { ...original };

copy.profile.name = "Mariam";

console.log(original.profile.name);
// Mariam

The top-level object was copied. The nested profile object was not.

For deep cloning, use structuredClone() when your data supports it.

6. Use rest parameters instead of arguments

Older JavaScript code often uses arguments:

function sum() {
  return Array.from(arguments).reduce((total, number) => {
    return total + number;
  }, 0);
}

Modern JavaScript has rest parameters:

function sum(...numbers) {
  return numbers.reduce((total, number) => total + number, 0);
}

console.log(sum(2, 4, 6));
// 12

Rest parameters give you a real array. That means you can use map(), filter(), reduce(), and every other array method immediately.

Mix normal parameters with rest parameters

function logMessage(level, ...messages) {
  console.log(`[${level}]`, messages.join(" "));
}

logMessage("info", "User", "logged", "in");
// [info] User logged in

Useful example

function createClassName(...classes) {
  return classes.filter(Boolean).join(" ");
}

const buttonClass = createClassName(
  "button",
  false && "button-disabled",
  "button-primary"
);

console.log(buttonClass);
// button button-primary

This pattern is useful in UI code.

7. Remove duplicates with Set

A Set stores unique values.

const tags = ["js", "react", "js", "node", "react"];

const uniqueTags = [...new Set(tags)];

console.log(uniqueTags);
// ["js", "react", "node"]

This is a clean way to remove duplicate strings, numbers, or booleans.

Remove duplicate IDs

const userIds = [1, 2, 2, 3, 4, 4];

const uniqueUserIds = [...new Set(userIds)];

console.log(uniqueUserIds);
// [1, 2, 3, 4]

Check if a value exists

const allowedRoles = new Set(["admin", "editor", "author"]);

console.log(allowedRoles.has("editor"));
// true

For repeated lookup checks, Set is usually cleaner than an array with many includes() calls.

Duplicates in arrays of objects

Set does not remove duplicate objects by content:

const users = [
  { id: 1, name: "Ani" },
  { id: 1, name: "Ani" }
];

console.log([...new Set(users)]);
// Both objects remain

Objects are compared by reference, not by shape.

For object arrays, use a Map:

const users = [
  { id: 1, name: "Ani" },
  { id: 2, name: "Aram" },
  { id: 1, name: "Ani" }
];

const uniqueUsers = [
  ...new Map(users.map(user => [user.id, user])).values()
];

console.log(uniqueUsers);
// [{ id: 1, name: "Ani" }, { id: 2, name: "Aram" }]

8. Use Map for cleaner key-value storage

Objects are fine for many key-value tasks. But Map is better when your keys are dynamic or not always strings.

const userScores = new Map();

userScores.set("Ani", 95);
userScores.set("Aram", 88);

console.log(userScores.get("Ani"));
// 95

Why use Map?

A Map has methods made for key-value data:

userScores.has("Ani");
userScores.delete("Aram");
userScores.size;

You can loop over it cleanly:

for (const [name, score] of userScores) {
  console.log(`${name}: ${score}`);
}

Use objects for structured data

Use an object when you are describing one thing:

const user = {
  id: 1,
  name: "Ani",
  role: "admin"
};

Use a Map when you are storing a collection of relationships:

const permissionsByRole = new Map();

permissionsByRole.set("admin", ["read", "write", "delete"]);
permissionsByRole.set("editor", ["read", "write"]);
permissionsByRole.set("viewer", ["read"]);

That difference keeps your code easier to reason about.

9. Use Array.from() to create real arrays

Some values look like arrays but are not arrays.

For example, DOM collections:

const buttons = document.querySelectorAll("button");

console.log(Array.isArray(buttons));
// false

You can turn them into a real array:

const buttonArray = Array.from(buttons);

buttonArray.map(button => button.textContent);

You can also use Array.from() with a mapping function:

const numbers = Array.from({ length: 5 }, (_, index) => index + 1);

console.log(numbers);
// [1, 2, 3, 4, 5]

That is useful when generating lists.

Create years for a dropdown

const currentYear = new Date().getFullYear();

const years = Array.from({ length: 10 }, (_, index) => {
  return currentYear + index;
});

console.log(years);
// [2026, 2027, 2028, ...]

Convert a string to characters

const letters = Array.from("JavaScript");

console.log(letters);
// ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]

10. Use flatMap() when you need map plus flatten

Sometimes you map over an array and return arrays inside it.

const sentences = [
  "JavaScript is useful",
  "Tips and tricks help"
];

const words = sentences.map(sentence => sentence.split(" "));

console.log(words);
// [["JavaScript", "is", "useful"], ["Tips", "and", "tricks", "help"]]

If you want one flat array, use flatMap():

const words = sentences.flatMap(sentence => sentence.split(" "));

console.log(words);
// ["JavaScript", "is", "useful", "Tips", "and", "tricks", "help"]

Real example: extract product tags

const products = [
  { name: "Laptop", tags: ["tech", "work"] },
  { name: "Phone", tags: ["tech", "mobile"] }
];

const tags = products.flatMap(product => product.tags);

console.log(tags);
// ["tech", "work", "tech", "mobile"]

Combine it with Set to get unique tags:

const uniqueTags = [...new Set(products.flatMap(product => product.tags))];

console.log(uniqueTags);
// ["tech", "work", "mobile"]

That is a nice example of small JavaScript tricks working together.

11. Use Object.hasOwn() for safer property checks

You may have seen this:

if (user.hasOwnProperty("email")) {
  console.log(user.email);
}

The problem is that hasOwnProperty can be missing or overwritten.

A safer modern option is Object.hasOwn():

const user = {
  name: "Ani",
  email: "ani@example.com"
};

console.log(Object.hasOwn(user, "email"));
// true

Why it matters

This object does not inherit from Object.prototype:

const data = Object.create(null);

data.email = "test@example.com";

console.log(data.hasOwnProperty);
// undefined

But this still works:

console.log(Object.hasOwn(data, "email"));
// true

Use case: validate incoming data

function hasRequiredFields(input) {
  return (
    Object.hasOwn(input, "email") &&
    Object.hasOwn(input, "password")
  );
}

Use this when you need to know whether a property exists directly on the object.

12. Deep clone data with structuredClone()

Many developers use this old trick to deep clone objects:

const copy = JSON.parse(JSON.stringify(original));

It works for simple data, but it has problems. It can lose values like Date, Map, Set, undefined, and more.

Modern JavaScript gives you structuredClone():

const original = {
  name: "Ani",
  preferences: {
    theme: "dark"
  }
};

const copy = structuredClone(original);

copy.preferences.theme = "light";

console.log(original.preferences.theme);
// dark

The nested object is copied properly.

Works with more than plain objects

const original = {
  createdAt: new Date(),
  tags: new Set(["js", "web"])
};

const copy = structuredClone(original);

console.log(copy.createdAt instanceof Date);
// true

console.log(copy.tags instanceof Set);
// true

What it cannot clone

structuredClone() cannot clone everything. Functions are not cloneable:

const data = {
  name: "test",
  run() {
    console.log("running");
  }
};

const copy = structuredClone(data);
// DataCloneError

Use it for data, not behavior.

13. Run independent async tasks with Promise.all()

If two async tasks do not depend on each other, do not run them one by one.

Slow version:

const user = await fetchUser();
const orders = await fetchOrders();

Better version:

const [user, orders] = await Promise.all([
  fetchUser(),
  fetchOrders()
]);

Both requests start at the same time.

Real example

async function loadDashboard() {
  const [profile, notifications, stats] = await Promise.all([
    fetchProfile(),
    fetchNotifications(),
    fetchStats()
  ]);

  return {
    profile,
    notifications,
    stats
  };
}

This is one of the most useful advanced JavaScript techniques for frontend and Node.js code.

Important behavior

Promise.all() fails fast. If one promise rejects, the whole Promise.all() rejects.

try {
  const results = await Promise.all([
    fetchUser(),
    fetchOrders(),
    fetchInvoices()
  ]);

  console.log(results);
} catch (error) {
  console.error("At least one request failed", error);
}

If you need the result of every request, even failed ones, use the next trick.

14. Use Promise.allSettled() for partial failures

Sometimes one failed request should not break everything.

Example: a dashboard can still show the user profile even if notifications fail.

const results = await Promise.allSettled([
  fetchProfile(),
  fetchNotifications(),
  fetchStats()
]);

console.log(results);

Each result tells you whether it was fulfilled or rejected.

[
  { status: "fulfilled", value: { name: "Ani" } },
  { status: "rejected", reason: Error("Failed") },
  { status: "fulfilled", value: { visits: 120 } }
]

Cleaner helper

function getFulfilledValues(results) {
  return results
    .filter(result => result.status === "fulfilled")
    .map(result => result.value);
}

Real example

async function loadOptionalDashboardData() {
  const results = await Promise.allSettled([
    fetchRecommendations(),
    fetchRecentActivity(),
    fetchPromotions()
  ]);

  return {
    recommendations:
      results[0].status === "fulfilled" ? results[0].value : [],
    recentActivity:
      results[1].status === "fulfilled" ? results[1].value : [],
    promotions:
      results[2].status === "fulfilled" ? results[2].value : []
  };
}

Use Promise.all() when everything must succeed. Use Promise.allSettled() when partial success is acceptable.

15. Cancel fetch requests with AbortController

Users click around. They type quickly. They leave pages before requests finish.

If your app keeps old requests alive, you can show stale data or waste network resources.

Use AbortController to cancel a request:

const controller = new AbortController();

fetch("/api/search?q=javascript", {
  signal: controller.signal
});

controller.abort();

Search input example

let currentController;

async function searchProducts(query) {
  if (currentController) {
    currentController.abort();
  }

  currentController = new AbortController();

  try {
    const response = await fetch(`/api/products?q=${query}`, {
      signal: currentController.signal
    });

    const data = await response.json();
    return data;
  } catch (error) {
    if (error.name === "AbortError") {
      return [];
    }

    throw error;
  }
}

This helps avoid race conditions where an older request finishes after a newer one.

Timeout example

async function fetchWithTimeout(url, timeout = 5000) {
  const controller = new AbortController();

  const timeoutId = setTimeout(() => {
    controller.abort();
  }, timeout);

  try {
    const response = await fetch(url, {
      signal: controller.signal
    });

    return response.json();
  } finally {
    clearTimeout(timeoutId);
  }
}

This is practical JavaScript, not just a trick.

16. Use URLSearchParams for query strings

Building query strings manually is asking for bugs.

Bad:

const url = "/search?q=" + query + "&page=" + page;

If query has spaces, symbols, or special characters, things can break.

Use URLSearchParams:

const params = new URLSearchParams();

params.set("q", "javascript tips");
params.set("page", "1");

const url = `/search?${params.toString()}`;

console.log(url);
// /search?q=javascript+tips&page=1

Create params from an object

const filters = {
  q: "javascript tricks",
  category: "web development",
  page: "2"
};

const params = new URLSearchParams(filters);

console.log(params.toString());
// q=javascript+tricks&category=web+development&page=2

Read query params

const params = new URLSearchParams(window.location.search);

const page = params.get("page") ?? "1";
const query = params.get("q") ?? "";

console.log(page, query);

This is useful for search pages, filters, pagination, dashboards, and shareable URLs.

17. Format numbers and currency with Intl.NumberFormat

Do not manually format money like this:

const price = "$" + amount.toFixed(2);

That assumes the currency, decimal style, and locale.

Use Intl.NumberFormat:

const formatter = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD"
});

console.log(formatter.format(1299.99));
// $1,299.99

Armenian dram example

const formatter = new Intl.NumberFormat("hy-AM", {
  style: "currency",
  currency: "AMD"
});

console.log(formatter.format(15000));
// ֏15,000.00

Format compact numbers

const compactFormatter = new Intl.NumberFormat("en-US", {
  notation: "compact"
});

console.log(compactFormatter.format(1200000));
// 1.2M

Format percentages

const percentFormatter = new Intl.NumberFormat("en-US", {
  style: "percent",
  maximumFractionDigits: 1
});

console.log(percentFormatter.format(0.256));
// 25.6%

Use this for ecommerce prices, analytics dashboards, reports, and admin panels.

18. Load heavy code with dynamic imports

You do not always need to load everything upfront.

Dynamic imports let you load code only when needed:

async function openChart() {
  const chartModule = await import("./chart.js");

  chartModule.renderChart();
}

This can improve initial page load when a feature is used only sometimes.

Example: load admin tools only for admins

async function loadAdminTools(user) {
  if (user.role !== "admin") {
    return;
  }

  const { showAdminPanel } = await import("./admin-panel.js");

  showAdminPanel();
}

Example: load a library on demand

async function exportReport(data) {
  const { exportToCsv } = await import("./csv-export.js");

  return exportToCsv(data);
}

Dynamic imports are especially useful for charts, editors, maps, PDF tools, and admin-only features.

Do not overuse them. Splitting tiny files can make code harder to follow. Use dynamic imports for code that is expensive or rarely needed.

19. Use guard clauses to avoid nested code

Deep nesting makes functions harder to read.

Bad:

function getDiscount(user) {
  if (user) {
    if (user.isActive) {
      if (user.orders > 10) {
        return 0.2;
      }

      return 0.1;
    }
  }

  return 0;
}

Use guard clauses:

function getDiscount(user) {
  if (!user) return 0;
  if (!user.isActive) return 0;

  if (user.orders > 10) {
    return 0.2;
  }

  return 0.1;
}

The logic is the same, but the function is easier to scan.

Another example

function submitForm(form) {
  if (!form.email) {
    return {
      success: false,
      error: "Email is required"
    };
  }

  if (!form.password) {
    return {
      success: false,
      error: "Password is required"
    };
  }

  return {
    success: true
  };
}

Guard clauses are not fancy. They just make code less annoying.

20. Debounce frequent function calls

Some events fire a lot.

Typing, scrolling, resizing, and mouse movement can trigger functions many times per second. If each event causes an API call or expensive calculation, your app will feel slow.

Debouncing waits until the user stops triggering the event.

function debounce(callback, delay) {
  let timeoutId;

  return function (...args) {
    clearTimeout(timeoutId);

    timeoutId = setTimeout(() => {
      callback(...args);
    }, delay);
  };
}

Search example

const searchInput = document.querySelector("#search");

const handleSearch = debounce(event => {
  console.log("Searching for:", event.target.value);
}, 300);

searchInput.addEventListener("input", handleSearch);

If the user types “javascript”, the function does not run for every letter. It runs after the user pauses.

API search example

const search = debounce(async query => {
  const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
  const results = await response.json();

  console.log(results);
}, 400);

Debounce vs throttle

Use debounce when you want to wait until activity stops.

Good examples:

  • Search input
  • Form validation
  • Auto-saving drafts
  • Window resize calculations

Use throttle when you want a function to run at most once every fixed interval.

Good examples:

  • Scroll tracking
  • Dragging
  • Mouse movement
  • Repeated button actions

Bonus: combine small tricks for cleaner real-world code

The best JavaScript tricks are often useful together.

Here is a small example that uses optional chaining, nullish coalescing, URLSearchParams, AbortController, and guard clauses.

let activeController;

async function searchUsers(filters = {}) {
  const query = filters.query?.trim() ?? "";

  if (query.length < 2) {
    return [];
  }

  if (activeController) {
    activeController.abort();
  }

  activeController = new AbortController();

  const params = new URLSearchParams({
    q: query,
    page: String(filters.page ?? 1),
    limit: String(filters.limit ?? 20)
  });

  try {
    const response = await fetch(`/api/users?${params.toString()}`, {
      signal: activeController.signal
    });

    if (!response.ok) {
      throw new Error("Failed to search users");
    }

    return response.json();
  } catch (error) {
    if (error.name === "AbortError") {
      return [];
    }

    throw error;
  }
}

This is the kind of JavaScript that ages well. It is not trying to impress anyone. It handles normal problems clearly.

Common JavaScript mistakes these tricks help you avoid

Treating 0, false, and "" as missing values

Use ?? instead of || when those values are valid.

const count = userCount ?? 0;

Crashing on missing API fields

Use optional chaining when a field is genuinely optional.

const image = product?.images?.[0]?.url;

Mutating original data by accident

Use spread for shallow copies and structuredClone() for deep data copies.

const updatedUser = {
  ...user,
  name: "Updated name"
};

Running async tasks too slowly

Use Promise.all() when tasks can run together.

const [user, settings] = await Promise.all([
  fetchUser(),
  fetchSettings()
]);

Letting old requests overwrite new results

Use AbortController for search, filters, and fast-changing views.

controller.abort();

How to get better at JavaScript

Learning more syntax is useful, but it is not enough.

The fastest way to get better at JavaScript is to work on the same boring problems repeatedly:

  • Fetch data and handle errors.
  • Transform arrays without mutating them.
  • Read unknown API data safely.
  • Write functions that return early when input is invalid.
  • Replace unclear code with names that explain intent.
  • Review old code and ask, “Would I understand this in three months?”

You do not need to memorize every method on MDN. You need to recognize common problems and know which tool fits.

Start with these:

?.       // optional chaining
??       // nullish coalescing
...      // spread and rest
Set      // unique values
Map      // key-value collections
Promise.all()
Promise.allSettled()
structuredClone()
AbortController
URLSearchParams
Intl.NumberFormat

If you understand those well, your JavaScript will already feel cleaner.

JavaScript tips and tricks for beginners

If you are still new to JavaScript, start with these five:

  1. Optional chaining
  2. Nullish coalescing
  3. Destructuring
  4. Spread syntax
  5. Array methods like map(), filter(), and reduce()

Do not rush into advanced patterns before you are comfortable with the basics.

A beginner should be able to read this code and explain what it does:

const activeUsers = users
  .filter(user => user.isActive)
  .map(user => ({
    id: user.id,
    name: user.name,
    email: user.email ?? "No email"
  }));

That one example includes filtering, mapping, object returns, and fallback values.

Advanced JavaScript techniques worth learning next

After you are comfortable with the tricks in this guide, move into deeper topics:

  • Closures
  • Prototypes
  • Event loop
  • Microtasks and macrotasks
  • Modules
  • Memory leaks
  • Browser rendering
  • TypeScript
  • Testing
  • Design patterns
  • Performance profiling

Here is a small closure example:

function createCounter() {
  let count = 0;

  return function increment() {
    count += 1;
    return count;
  };
}

const counter = createCounter();

console.log(counter());
// 1

console.log(counter());
// 2

Closures are not just interview material. They appear in event handlers, state management, memoization, and utility functions like debounce.

FAQ

What are the best JavaScript tips and tricks?

The best JavaScript tips and tricks are the ones that make your code safer and easier to read. Optional chaining, nullish coalescing, destructuring, spread syntax, Set, Map, Promise.all(), Promise.allSettled(), AbortController, and URLSearchParams are among the most useful in daily development.

Are these JavaScript tips and tricks for beginners?

Yes. Many of these are beginner friendly, especially optional chaining, destructuring, spread syntax, and Set. A few, like AbortController, dynamic imports, and Promise.allSettled(), are better once you are comfortable with async JavaScript.

Can I use this as a JavaScript tips and tricks PDF?

Yes. This guide is structured so it can be exported as a JavaScript tips and tricks PDF. The tables, examples, and FAQ sections are already organized for reading or sharing.

Are Reddit JavaScript tips and tricks useful?

Reddit can be useful for discovering problems developers face in real projects. The downside is that discussion threads are not always organized. Use Reddit for ideas, but verify the final syntax and behavior with official documentation.

Are GitHub JavaScript tips and tricks repositories worth reading?

Yes, especially when they include real examples. GitHub collections are useful for quick snippets, but they often lack explanation. If you copy a trick from GitHub, make sure you understand the tradeoff before adding it to production code.

What are some JavaScript advanced code examples?

Good advanced JavaScript code examples include debounced search, cancelable fetch requests, parallel API loading with Promise.all(), partial failure handling with Promise.allSettled(), dynamic imports for large modules, and deep cloning with structuredClone().

Do these tips apply to WinCC Unified JavaScript scripting?

Some general JavaScript ideas apply, such as variables, functions, conditions, arrays, objects, and clean formatting. But WinCC Unified has its own scripting environment and platform-specific APIs. If you are working with SIMATIC WinCC Unified JavaScript tips and tricks, check the official Siemens scripting documentation before using browser or Node.js-specific examples.

What is the best way to practice JavaScript tricks?

Take a small project and refactor it. Replace unsafe nested access with optional chaining. Replace weak defaults with ??. Convert repeated loops into array methods. Add proper async handling. You learn faster when you improve real code instead of only reading examples.

Final thoughts

JavaScript tricks are useful only when they make the code clearer.

A one-line solution is not automatically better. Sometimes the boring version is the better version. Good JavaScript is code that handles real data, fails safely, and still makes sense when someone else reads it later.

Start with the small improvements:

const name = user?.profile?.name ?? "Guest";

Then build up to cleaner async flows, better data handling, and smarter browser APIs.

That is how you get better at JavaScript: not by memorizing tricks, but by learning when each one actually helps.