class User {
constructor(email, passwordHash, createdAt) {
this.email = email;
this.passwordHash = passwordHash;
this.createdAt = createdAt;
}
toJSON() { return { email: this.email, createdAt: this.createdAt }; }
}
const u = new User("a@b.co", "x9", new Date(Date.UTC(2026, 0, 1)));
console.log(JSON.stringify(u));
{"email":"a@b.co","createdAt":"2026-01-01T00:00:00.000Z"}It prints {"email":"a@b.co","createdAt":"2026-01-01T00:00:00.000Z"}. JSON.stringify calls the object's toJSON() and serializes its result, so passwordHash is left out. The result holds a Date, and Date has its own toJSON(), which returns an ISO string.
"{"email":"a@b.co","createdAt":{}}" is tempting, because a Date has no own properties to list. But toJSON is checked on every value, including nested ones.