Thuta Learning
ExercisesProgrammingbeginner

Practice: Advanced JS Challenges

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Work through the Advanced JS Challenges practice set on your own
  • Practice and solidify the skills you've already learned
  • Get comfortable finding bugs, fixing them, and checking your own work

Let's think this through for a moment

This practice set combines concepts from the Advanced Concepts, OOP, and Async JavaScript chapters — closures, arrow functions, destructuring, classes, and promises/async-await — into tougher, more real-world-like scenarios. It's a step up from Exercise 1: instead of testing one concept at a time, these tasks make you combine two concepts together (for example, closures + higher-order functions). Try spending 10-15 minutes thinking it through yourself before checking the solution. Harder challenges like these are also great practice for interview prep.

Exercises

Task 1: Using a closure, write a `createCounter()` factory function that returns an object with `increment()`, `decrement()`, and `reset()` methods — the internal count variable should not be directly accessible from outside. Task 2: Build a `Person` class whose constructor takes name and age, and add a static method `compareAge(p1, p2)` that returns whichever person is older. Task 3: Write an async function called `fetchUserData(id)` (simulate the promise with `setTimeout`) and use async/await with try/catch to handle errors. Task 4: Using destructuring and the spread operator on an array of objects, chain `map()` and `filter()` together to pull out just the names of items priced under 1000 as an array.

Code Example

javascript
// Task 1: Closure counter factory
function createCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    decrement: () => --count,
    reset: () => (count = 0)
  };
}

// Task 2: Person class with static method
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  static compareAge(p1, p2) {
    // TODO: age ကြီးတဲ့ Person object ကို ပြန်ပေးပါ
  }
}

// Task 3: Async/await with error handling
function fetchUserData(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id <= 0) reject(new Error("Invalid user id"));
      else resolve({ id, name: "User " + id });
    }, 500);
  });
}

async function loadUser(id) {
  try {
    const user = await fetchUserData(id);
    console.log(user);
  } catch (err) {
    // TODO: error ကို handle လုပ်ပါ
  }
}

// Task 4: destructuring + map/filter chain
const products = [
  { name: "Pen", price: 500 },
  { name: "Bag", price: 15000 },
  { name: "Book", price: 800 }
];
const cheapNames = products
  .filter(({ price }) => price < 1000)
  .map(({ name }) => name);
console.log(cheapNames);
You should see
You should get the increment/decrement/reset results from the Counter object, the older Person object from `compareAge`, the user data (or a caught error message) from `loadUser(id)`, and a `["Pen", "Book"]` array for `cheapNames`.

Try it for 5 minutes

Take 5 minutes to call Task 3's function with `loadUser(-1)` and check whether the error path is handled properly.

A quick word of caution

Try rewriting Task 3 using `.then().catch()` instead of async/await, and compare the readability of both versions yourself — this kind of comparison is a genuinely useful debugging skill for real projects.

Easy traps

  • Exposing a closure's private variable directly as an object property, which breaks encapsulation
  • Forgetting `await` inside an `async` function and using the Promise object directly, which gives you an `[object Promise]` output

Now try it yourself

Take 5 minutes to call Task 3's function with `loadUser(-1)` and check whether the error path is handled properly.

You'll know it worked when: You should get the increment/decrement/reset results from the Counter object, the older Person object from `compareAge`, the user data (or a caught error message) from `loadUser(id)`, and a `["Pen", "Book"]` array for `cheapNames`.

Practice: Advanced JS Challenges | Thuta Learning