JavaScript · Syntax · Beginner

OOP, objects, algorithmic thinking

15 tasks

JavaScript exercises on OOP, objects, and algorithmic thinking: classes for data analysis, word and character counting, working with ratings, passwords, statistics, and object transformations.

Plain objects as class state

#
When a class needs to track a variable number of items — grades for many students, scores for many players, words in a text — a plain object {} stored on this is the right tool. A separate property per item would not scale. ```javascript class GradeBook { constructor() { this.grades = {}; } add(name, grade) { if (!(name in this.grades)) { this.grades[name] = []; } this.grades[name].push(grade); } average(name) { const grades = this.grades[name] || []; if (grades.length === 0) return 0; return grades.reduce((sum, g) => sum + g, 0) / grades.length; } } ``` this.grades is initialized as an empty object in constructor. The name in this.grades check tests whether the key already exists. || [] is a safe fallback when a key might be missing. For counting occurrences — word frequency, letter counts — the same pattern with a number value: ```javascript class WordCounter { constructor(text) { this.text = text; } count() { const result = {}; for (const word of this.text.split(" ")) { result[word] = (result[word] || 0) + 1; } return result; } } ``` result[word] || 0 returns the current count if the key exists, or 0 if it does not. Adding 1 gives the new count. This is the standard dictionary-counting idiom in JavaScript.

Registry, counter, and aggregator patterns

#
A registry that prevents duplicates — use a Set to store registered names: ```javascript class UserRegistry { constructor() { this.users = new Set(); } register(username) { if (this.users.has(username)) { return false; } this.users.add(username); return true; } } ``` Set.has() is equivalent to Python's in for sets. Set.add() adds an element. A class with a balance that enforces a rule: ```javascript class BankAccount { constructor() { this.balance = 0; } deposit(amount) { this.balance += amount; } withdraw(amount) { if (amount > this.balance) { return false; } this.balance -= amount; return true; } } ``` Finding the top player — iterate over the object entries, track the key with the maximum value: ```javascript class ScoreTable { constructor() { this.scores = {}; } add(name, points) { this.scores[name] = (this.scores[name] || 0) + points; } topPlayer() { let topName = null; let topScore = -Infinity; for (const [name, score] of Object.entries(this.scores)) { if (score > topScore) { topScore = score; topName = name; } } return topName; } } ``` Object.entries() gives [key, value] pairs, which you can destructure directly in the for...of loop. -Infinity ensures any real score beats the initial value.
01

WordCounter for text.

#

Create a WordCounter class that takes a text string. Add a count method that returns an object where: - the key is a word - the value is how many times it appears in the text

class WordCounter {
    // your code here
}
Solution
class WordCounter {
    constructor(text) {
        this.text = text;
    }

    count() {
        let result = {};

        let words = this.text.trim()
            ? this.text.trim().split(/\s+/)
            : [];

        for (let w of words) {
            if (w in result) {
                result[w] += 1;
            } else {
                result[w] = 1;
            }
        }

        return result;
    }
}
02

GradeBook journal.

#

Create a GradeBook class. The add(name, grade) method adds a grade for a student. The average(name) method returns the student's average grade.

class GradeBook {
    // your code here
}
Solution
class GradeBook {
    constructor() {
        this.data = {};
    }

    add(name, grade) {
        if (!(name in this.data)) {
            this.data[name] = [];
        }

        this.data[name].push(grade);
    }

    average(name) {
        let grades = this.data[name] ?? [];

        if (grades.length === 0) {
            return 0;
        }

        return grades.reduce((total, value) => total + value, 0) / grades.length;
    }
}
03

Counting each letter.

#

Write a function that takes a string and returns an object with the count of each letter.

function letterStats(text) {
    // your code here
}
Solution
function letterStats(text) {
    let result = {};

    for (let ch of text) {
        if (/^\p{L}$/u.test(ch)) {
            ch = ch.toLowerCase();

            if (ch in result) {
                result[ch] += 1;
            } else {
                result[ch] = 1;
            }
        }
    }

    return result;
}
04

Password strength check.

#

Create a PasswordChecker class. The check method returns true if the password: - length ≥ 8 - contains at least one digit

class PasswordChecker {
    // your code here
}
Solution
class PasswordChecker {
    check(password) {
        if (password.length < 8) {
            return false;
        }

        let hasDigit = false;

        for (let ch of password) {
            if (/^\d$/.test(ch)) {
                hasDigit = true;
                break;
            }
        }

        return hasDigit;
    }
}
05

Inventory of items.

#

Create an Inventory class. The addItem(name, count) method adds an item. The totalItems() method returns the total quantity of all items.

class Inventory {
    // your code here
}
Solution
class Inventory {
    constructor() {
        this.items = {};
    }

    addItem(name, count) {
        if (name in this.items) {
            this.items[name] += count;
        } else {
            this.items[name] = count;
        }
    }

    totalItems() {
        let total = 0;

        for (let c of Object.values(this.items)) {
            total += c;
        }

        return total;
    }
}
06

Grouping words by length.

#

Write a function that takes an array of words and returns an object: - the key is the word length - the value is how many words have that length

function lengthGroups(words) {
    // your code here
}
Solution
function lengthGroups(words) {
    let result = {};

    for (let w of words) {
        let l = w.length;

        if (l in result) {
            result[l] += 1;
        } else {
            result[l] = 1;
        }
    }

    return result;
}
07

BankAccount without going negative.

#

Create a BankAccount class with methods: - deposit(amount) - withdraw(amount) — does not allow the balance to go negative

class BankAccount {
    // your code here
}
Solution
class BankAccount {
    constructor(balance) {
        this.balance = balance;
    }
    deposit(amount) {
        this.balance += amount;
    }
    withdraw(amount) {
        if (amount <= this.balance) {
            this.balance -= amount;
            return true;
        }
        return false;
    }
}
08

Vowels and consonants.

#

Write a function that takes a string and returns an object with the number of vowels and consonants.

function vowelsAndConsonants(text) {
    // your code here
}
Solution
function vowelsAndConsonants(text) {
    let vowels = "aeiou";

    let result = {
        vowels: 0,
        consonants: 0
    };

    for (let ch of text.toLowerCase()) {
        if (/^\p{L}$/u.test(ch)) {

            if (vowels.includes(ch)) {
                result.vowels += 1;

            } else {
                result.consonants += 1;
            }
        }
    }

    return result;
}
09

User registration.

#

Create a UserRegistry class. The register(username) method: - returns true if the user was added - false if such a user already exists

let users = [];

class UserRegistry {
    // your code here
}
Solution
let users = [];

class UserRegistry {
    register(username) {
        if (users.includes(username)) {
            return false;
        }

        users.push(username);

        return true;
    }
}
10

Number classification.

#

Write a function that takes an array of numbers and returns an object: - "positive" - "negative" - "zero"

function numberSummary(nums) {
    // your code here
}
Solution
function numberSummary(nums) {
    let result = {"positive": 0, "negative": 0, "zero": 0};
    for (let n of nums) {
        if (n > 0) {
            result["positive"] += 1;
        } else if (n < 0) {
            result["negative"] += 1;
        } else {
            result["zero"] += 1;
        }
    }
    return result;
}
11

Shopping cart.

#

Create a ShoppingCart class. The add(product, price) method adds a product. The total() method returns the sum of all prices.

class ShoppingCart {
    // your code here
}
Solution
class ShoppingCart {
    constructor() {
        this.items = {};
    }
    add(product, price) {
        this.items[product] = price;
    }
    total() {
        let total = 0;
        for (let p of Object.values(this.items)) {
            total += p;
        }
        return total;
    }
}
12

Position of the first occurrence of a character.

#

Write a function that takes a string and returns an object where the key is a character, and the value is the position of its first occurrence in the string.

function firstPositions(text) {
    // your code here
}
Solution
function firstPositions(text) {
    let result = {};

    for (let i = 0; i < text.length; i++) {
        if (!(text[i] in result)) {
            result[text[i]] = i;
        }
    }

    return result;
}
13

Player score table.

#

Create a ScoreTable class. The add(name, ponumbers) method adds points to a player. The top_Player() method returns the name of the player with the highest score.

class ScoreTable {
    // your code here
}
Solution
class ScoreTable {
    constructor() {
        this.scores = {};
    }

    add(name, points) {
        if (name in this.scores) {
            this.scores[name] += points;
        } else {
            this.scores[name] = points;
        }
    }

    topPlayer() {
        let names = Object.keys(this.scores);

        if (names.length === 0) {
            return null;
        }

        let top = null;
        let maxScore = -1;

        for (const [name, score] of Object.entries(this.scores)) {
            if (score > maxScore) {
                maxScore = score;
                top = name;
            }
        }

        return top;
    }
}
14

Swapping keys and values.

#

Write a function that takes an object and returns a new object where keys and values are swapped. It is guaranteed that the values are unique.

function swapDict(d) {
    // your code here
}
Solution
function swapDict(d) {
    let result = {};
    for (const [k, v] of Object.entries(d)) {
        result[v] = k;
    }
    return result;
}
15

Text analyzer.

#

Create a TextAnalyzer class. The analyze method returns an object: - "chars" — number of characters - "words" — number of words - "lines" — number of lines

class TextAnalyzer {
    // your code here
}
Solution
class TextAnalyzer {
    constructor(text) {
        this.text = text;
    }

    analyze() {
        const chars = this.text.length;
        const words = this.text.trim() ? this.text.trim().split(/\s+/).length : 0;
        const lines = this.text ? this.text.split("\n").length : 0;

        return {
            chars,
            words,
            lines,
        };
    }
}