Lección 5 · 5 de 20
Getters, setters y campos privados · JavaScript
Proteja el estado de sus objetos en JavaScript con campos privados #, valide valores con setters y calcule propiedades con getters.

Los campos que empiezan por `#` son privados: solo el código de dentro de la clase puede leerlos o cambiarlos. #price y #changes se declaran arriba, con su valor inicial, y desde fuera no existen: mouse["#price"] da undefined y Object.keys(mouse) solo muestra name. Escribir mouse.#price fuera de la clase sería un error de sintaxis.
Un setter (set price(value)) parece una propiedad normal, pero ejecuta código al asignar. Por eso mouse.price = 18 pasa por la validación y mouse.price = -3 lanza un RangeError, que el programa captura y muestra. Incluso el constructor usa this.price = price, así que el precio inicial también se valida y cuenta como cambio: de ahí los 2 changes.
Un getter (get price()) se lee sin paréntesis: mouse.price. Sirve además para propiedades calculadas: priceWithVat no se guarda en ningún sitio, se calcula cada vez a partir de #price. Como no tiene setter, la asignación mouse.priceWithVat = 1 no hace nada (en modo estricto lanzaría un TypeError).
Juntos, los campos privados, los getters y los setters permiten encapsular: el objeto decide qué se ve, qué se puede cambiar y con qué reglas, y nadie puede dejarlo en un estado incorrecto, como un producto con precio negativo.
Código · main.js
class Product { #price = 0; // private: only code inside the class can touch it #changes = 0; constructor(name, price) { this.name = name; this.price = price; // goes through the setter below } get price() { return this.#price; } set price(value) { if (typeof value !== "number" || value < 0) { throw new RangeError(`Invalid price for ${this.name}: ${value}`); } this.#price = value; this.#changes++; } get priceWithVat() { return +(this.#price * 1.21).toFixed(2); } get changes() { return this.#changes; }}const mouse = new Product("Mouse", 20);mouse.price = 18;console.log(mouse.name, mouse.price, "->", mouse.priceWithVat, "with VAT");try { mouse.price = -3; } catch (err) { console.log(`${err.name}: ${err.message}`); }console.log("Price is still", mouse.price, "after", mouse.changes, "changes");mouse.priceWithVat = 1; // a getter without a setter ignores assignmentsconsole.log("With VAT:", mouse.priceWithVat, "| keys:", Object.keys(mouse).join(", "));console.log("From outside:", mouse["#price"]);Salida · node main.js
Mouse 18 -> 21.78 with VAT RangeError: Invalid price for Mouse: -3 Price is still 18 after 2 changes With VAT: 21.78 | keys: name From outside: undefined
Para recordar
- Un campo
#privadosolo es accesible desde dentro de la clase. - Un setter valida o transforma el valor en cada asignación.
- Un getter se lee como una propiedad y puede calcular su valor.
- Un getter sin setter es una propiedad de solo lectura.
Ejercicio
Añada un setter discount que admita un porcentaje entre 0 y 50, lo guarde en un campo privado #discount y haga que priceWithVat lo descuente; pruebe un descuento válido y otro de 80.