Properties assigned to this in the constructor belong to each instance. Methods and accessors in the class body are shared on Animal.prototype. static members live on the class itself; instances reach them through this.constructor.
class Animal {
static count = 0; // static: lives on Animal itself
constructor(name) { this.name = name; Animal.count++; } // own property of each instance
eat() { return `${this.name} eats.`; } // shared, on Animal.prototype
whoami() { return `${this.constructor.name}: ${this.eat()}`; }
get intro() { return `This is ${this.name}.`; } // read like a property
set rename(n) { this.name = n; } // runs on assignment
static comment() { return 'Animals are cute.'; }
}
const b = new Animal('Brownie');
b.rename = 'Greenie';
console.log(b.intro, b.whoami(), Animal.comment(), Animal.count);
console.log(Object.keys(b), Object.hasOwn(Animal.prototype, 'eat'), typeof Animal);This is Greenie. Animal: Greenie eats. Animals are cute. 1 [ 'name' ] true function
A class is still a function, but its body is strict, its methods are non-enumerable, and calling it without new throws. A method passed as a callback loses this; bind it or wrap it in an arrow function.