Define objects with a shared behavior model
A class defines construction and methods for instances. JavaScript classes use the language's prototype-based object model. A class is not a separate system that replaces prototypes, and creating a class does not automatically make its public fields immutable.
class Progress {
#completed = 0;
constructor(course) {
if (typeof course !== 'string' || !course.trim()) {
throw new TypeError('Course name is required');
}
this.course = course.trim();
}
finish() {
this.#completed += 1;
return this.#completed;
}
get completed() { return this.#completed; }
}
const progress = new Progress('JavaScript');
console.log(progress.finish()); // 1
console.log(progress.completed); // 1
console.log(progress.course); // JavaScriptThe constructor establishes initial state. The private field can be accessed only within the class's permitted lexical scope. The getter exposes a read-only query without giving outside code a public counter field to assign directly.
Instance versus static behavior
An instance method operates through a particular object. A static method belongs to the class constructor itself, useful for a factory or validation helper. Do not call an instance method as though it were static or assume a static method can use an instance's fields without an instance.
Method receiver
progress.finish() supplies progress as this. Passing progress.finish as a standalone callback can lose that receiver. Use a wrapper such as () => progress.finish() or bind deliberately.
Encapsulation needs rules
Private syntax restricts direct access, but public methods must still validate their operations. If a score must stay within 0–100, every update path must preserve that rule. A class with dozens of unrestricted setters can expose the same invalid states as a plain object.
Practice
- Create two Progress instances and verify their counts are independent.
- Add reset and test that completed becomes zero.
- Attempt direct #completed access outside the class and read the syntax error in a disposable example.
- Explain why the public course field can still be reassigned even though #completed is private.