Symbols vs Private Fields

Symbols vs Private Class Fields

A module-scoped symbol only hides a property: reflection reveals it and spread copies it. A #private field (Private and Static Blocks) is not a property, so nothing outside the class reaches it. Use #private for encapsulation and symbols for keys that unrelated code must share, such as protocols.

A symbol key leaks; a private field does notJavaScriptLive
const ageSym = Symbol('age');
class BySymbol { constructor(age) { this[ageSym] = age; } }
class ByField { #age; constructor(age) { this.#age = age; } }
const p1 = new BySymbol(30), p2 = new ByField(30);
console.log(p1[Object.getOwnPropertySymbols(p1)[0]], Reflect.ownKeys(p2));
console.log(Object.getOwnPropertySymbols({ ...p1 }), Reflect.ownKeys({ ...p2 }));