Juan David Sánchez
Eliaz Bobadilla
Gracias!
Juan Castro
ProfesorSpoilers...
¿Cómo se encapsulan métodos y atributos en JavaScript?
JavaScript es un lenguaje con particularidades únicas que se manifiestan en diversas formas a la hora de trabajar con prototipos y clases. Aunque el encapsulamiento es un concepto familiar en muchos lenguajes, en JavaScript la forma de implementarlo difiere un poco. Aquí analizaremos cómo podemos proteger nuestros datos y métodos de cambios no deseados.
¿Cómo protegemos los atributos en JavaScript?
En lenguajes de programación tradicionales, es común marcar atributos como privado o público para controlar el acceso. Sin embargo, JavaScript no tiene un soporte nativo para el acceso privado. En su lugar, se sigue una convención: prefixar el nombre del atributo con un guion bajo (_). Este método pretende ser una señal amistosa a otros desarrolladores para que entiendan que esos atributos no deberían ser manipulados directamente desde fuera de la clase.
¿Qué son los getters y setters?
Getters y setters son métodos especiales que nos permiten interceptar y controlar el acceso a los propiedades de los objetos:
class Course { constructor(name) { this._name = name; // uso de prefijo para denotar privacidad } get name() { return this._name; // acceso controlado a la propiedad } set name(newName) { if (!newName.includes("malito")) { this._name = newName; } else { console.warn("Way, no puedes actualizar el curso con ese nombre."); } } } let curso = new Course("Curso gratis de programación básica"); console.log(curso.name); // Accede al nombre utilizando el getter curso.name = "Curso avanzado de programación"; // Modifica el nombre usando el setter console.log(curso.name); // Verifica el cambio
¿Cómo se previenen cambios indeseados?
Utilizando setters, podemos establecer restricciones o validaciones que deben cumplirse antes de modificar propiedades. En el caso ilustrado, se previene que el nombre del curso pueda incluir valores considerados inapropiados como "malito".
Desafíos y ejercicios
Practicar con getters y setters es esencial para dominar su uso en JavaScript. Aquí te propongo dos desafíos:
Estos pasos no solo consolidarán tu conocimiento sobre encapsulamiento en JavaScript, sino que también te prepararán para escribir código más robusto y sostenible. ¡Adelante, sigue explorando! Tu habilidad para gestionar la lógica de negocio con JavaScript crecerá exponencialmente con la práctica.
Juan David Sánchez
Eliaz Bobadilla
Gracias!
Juan Castro
ProfesorSpoilers...
Qué son los getters y setters Una función que obtiene un valor de una propiedad se llama getter y una que establece el valor de una propiedad se llama setter.
Esta característica a sido implementada en ES2015, pudiendo modificar el funcionamiento normal de establecer u obtener el valor de una propiedad, a estas se les conoce como accessor properties.
Funcionamiento En ocasiones queremos valores basados en otros valores, para esto los data accessors son bastante útiles.
Para crearlos usamos los keywords get y set
const obj = { get prop() { return this.__prop__; }, set prop(value) { this.__prop__ = value * 2; }, }; obj.prop = 12; console.log(obj.prop); //24
Creamos un objeto, con una única propiedad, que tiene un getter y un setter. de esta manera cada vez que establezcamos un valor para prop se multiplicará por dos.
Nota: utilice prop por convención, pero no implica que es un valor especial, este es un valor normal.
Otra manera de crear un accessor properties es de manera explícita usando Object.defineProperty
const obj = {}; Object.defineProperty(obj, //objeto target 'prop', //nombre propiedad { enumerable: true, configurable: true, get prop() { //getter return this.__prop__; }, set prop(value) { //setter this.__prop__ = value * 2; }, }); obj.prop = 12; var atr = Object.getOwnPropertyDescriptor(obj, 'prop') console.log(atr);
La ventaja que tenemos de esta manera, es que podemos establecer los atributos que queremos tenga la propiedad.
Edgar Ramón González Contreras
Juan Castro
ProfesorHermosa y elegante solución :clap:
Franks Jhon Colque Zegarra
Buen aporte!! :)
Angel Solis
César Palma
es la forma de encapsular antes de ES2020
Máximo Calderon
Mi respeto... Esto si es verdadero encapsulamiento.... Gracias por compartir este ejemplo....
Ezequiel Magi
Los getters y setters son geniales. Pero me paso algo extraño: si pongo cursoProgBasica .name = "Cualquier nombre" el SET comprueba que cumpla lo que le pedi. PEEEEROOO si pongo por consola: cursoProgBasica._name = "cualquier cosa" ME SALTEA la barrera del SET y me toma como correcto lo que ponga! A alguien mas le paso?
Juan Castro
ProfesorYes! ¡Así se hackea JavaScript! ¡MUY BIEN! . En el Curso Intermedio de POO en JS vamos a ver varias estrategias para combatir ese mismo problemita :D
Orangel Gonzalez
Es cierto, colocándolo así no da el error 🙃
Eliaz Bobadilla
Naz Villa
Getters se usan para acceder a las propiedades en un objeto.
Setters para cambiar or silenciar una propiedad en un objeto
Franks Jhon Colque Zegarra
Samuel Gómez Balderas
No olvides asignar la propiedad constructor de tu prototipo con el valor de tu función FibonacciGenerator para las posteriores validaciones de instancias.
Anfernee Valera
Los getters y setters son construcciones de los objetos que permiten acceder a valores del mismo sin revelar la forma de su implementación.
Guillermo Prituluk
Hackeado 😎😎
Ricardo Alfonso Chavez Vilcapoma
Que master 🤣
Henry Alexander Velásquez Rosas
Hackeado X2
Nos van a banear de Platzi 😂🤣
Sergio Camilo Garzón Pérez
Jully Evangelina Flórez Fonseca
Holas les comparto parte de mi código :)
muy interesante las clases he aprendido bastante
Servio Gabriel Pachard Velez
jajajajajaj
Gabriela Ramírez
Entiendo que con el uso de Getters and Setters podremos evitar errores al interactuar con los usuarios, ya que me permite selecionar los atributos de las clases y condicionarlos con validaciones de manera que el usuario cambie solo lo que nos interesa
Orangel Gonzalez
Lo que estoy viendo es que cuando trabajo con módulos me da error ❌
Pero cuando esta todo en un mismo archivo JS, si da bueno ✅
Larry Caycho
Juan Castro
Profesor¿Podrías mostrarnos tu código JavaScript? Al parecer ahí está el posible error.
Dario Paladines
Compañeros una cosa que me acabo de dar cuenta, que los más avanzados ya lo sabrán, pero realmente es un dolor de cabeza tener todas las clases, objetos, instancias, etc en el mismo .js ya que ahora que ejecute en la consola me salieron errores que revisando es por el orden de ejecución de las clases u objetos que deben ser declarados o inicializados previamente y como tenia TODO en el mismo .js ahí tratando de "ordenarlos" (que según yo estaba todo ordenado) caí en un bucle en el que todas las clases deben ser declaradas entre todas antes una y otra jaja osea queda una mezcla completa de código sin ningún orden, así que ahora entiendo porque lo hacen en diferentes archivos o bueno supongo que una de estas debe ser una razón
Kevin Acevedo
Este sólo es un ejemplo básico de lo que se puede hacer con getters y setters; sin embargo, leí en un post que como parte de las buenas prácticas de programación, incluso si no vas a modificar un atributo, todos los atributos en general deberían ser accedidos por medio de getters y setters. Como se vería el ejemplo de la clase si fuese directamente embebido en el objeto, sin una clase, con la restricción de que el valor** name **no puede ser una cadena vacía ni undefined.
var cursoProgBas = { name_value, clases, instructor, año, get name(){ return this.name_value; }, set name(nuevoNombrecito){ if(nuevoNombrecito === "" || typeof nuevoNombrecito === "undefined"){ console.error("El nombre no es válido o no ha sido asignado.") } else{ this.name_value = nuevoNombrecito; } } }
Brayan Torrealba Sáez
Me gusta!
Daniel Rodrigo Valdivieso Merino
ProfesorMigrant Cyborg
Paso mi code con una breve (boba) autenticación
get attributes(){ return { name: this._name, description: this._description, image: this._image } } set name({name, auth}){ if(auth !== 'soyadmin'){ console.error('Invalid Authorization') return false } else { this._name = name; } }
Julian Franco
Interesante siempre habia visto POO pero únicamente en Java y en JS es como BOOM!! Constante 🤯
Y me recuerda mucho a la POO en Python. Si porque Python también tiene POO
bruno guerra solano
mi pregunta es estoy revisando información sobre getter and setters y en su mayoría sale información de JAVA en la cual entiendo que si declaramos un método de tipo private este no es accesible desde otra clase y es allí donde utilizas los getter y setter pero en javascript si no podemos declarar como public o private que sentido tiene usarlos ? 🤔
Diego Alejandro
Por lo general es buena práctica usar getters y setters para modificar los atributos de cualquier clase evitando errores, por ejemplo, si tienes un atributo que puede tener únicamente un valor numérico, alguien más podría modificarlo llamándolo así
MyClass.myAtribute = 'I’m a string ';
sin embargo si lo tuviera que modificar con un getter, la función getter podría tener una validación para que únicamente admita valores numéricos y evite este tipo de errores.
Leonardo Moreno Faberón
Creo q entiendo tu pregunta. quiza en 6 meses ya sabes la respuesta pero aca voy a intentarlo. cuando estas programando y dias despues de instanciar tu objeto o varios eventos despues (eventos que han afectado a tu objeto). o quieres hacer eventos que modifiquen tu objeto. vas a desear que solo sea modificable lo que a ti como dev te convenga algunas props de tu objeto no querras que las toquen ni querras modificarlas tu mismo por algun error (que puede pasar). entonces tener propiedades privadas es desde php , java , creo q para todos los lenguajes vital vital vital. si js no los tiene yo lo considero un error pero hay gente muy habil que ha conseguido lograr emular el private para que sea mas seguro no romper tu propio programa. a veces viene otro desarrollador o tu mismo , te olvidaste como se llama tu instancia y le pones el nombre de otra instancia de otra clase y sobre ella empiezas a modificar atributos que no querias modificar (estas modificando una instancia de otro objeto que en principio ni querias modificar y quiza ni lo tienes en tu mente). luego tu app hace cualquier cosa menos lo que quieres.
En ES2020 se introdujo la sintaxis campos privados en las clases. Se hace uso de un numeral como prefijo del nombre de la variable. ¿Cúal sería la ventaja de usar esto? Que no existe la posibilidad de que alguien modifique la variable privada desde la instancia a menos de que use el setter que le dimos. Con el ejemplo en esta clase, quedaría así:
class Course { #name; constructor({ name, classes = [] }) { this.#name = name; this.classes = classes; } get name() { return this.#name; } set name(nuevoNombrecito) { if (nuevoNombrecito === 'Curso Malito de Programación Básica') { console.error('Web... no'); } else { this.#name = nuevoNombrecito; } } }
Me puse a jugar un rato con los "prototypes" y logre esto:
"use strict"; function Student(name, age, nationality) { this._name = name; this._age = age; this.nationality = nationality; } Student.prototype = { get name() { return this._name; }, set name(newName) { this._name = newName; }, get age() { return this._age; }, set age(newAge) { this._age = newAge; }, }; let edgar = new Student("Edgar", 25, "Mexico"); edgar.name = "Juan"; edgar.age = 30 console.log(edgar);
Funcionando al 100 :3
También una forma de emular encapsulamiento en javascript es por mediode los closures.
const counter = (() => { let privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: () => { changeBy(1); }, decrement: () => { changeBy(-1); }, value: () => { return privateCounter; } }; }); console.log(counter.value()); // 0. counter.increment(); counter.increment(); console.log(counter.value()); // 2. counter.decrement(); console.log(counter.value()); // 1.
Ejemplo sacado de MDN
Les dejo mi código sobre un manga xD usando la nueva sintaxis de #👇
const hasCopyright = false class Manga { #mangaka; #name; constructor({ name, mangaka }) { this.#name = name; this.#mangaka = mangaka; } get mangaka() { return this.#mangaka; } get name() { return this.#name; } set name(name) { if (hasCopyright) { console.log('This Manga name has copyright!'); } else { this.#name = name; } } } const REQUIEM_ADVENTURES = new Manga({ name: 'Requiem Adventures', mangaka: 'UltiRequiem', }); console.log(REQUIEM_ADVENTURES); console.log(REQUIEM_ADVENTURES.mangaka); console.log(REQUIEM_ADVENTURES.name); REQUIEM_ADVENTURES.name = 'Adventures Requiem?'; console.log(REQUIEM_ADVENTURES.name);
Tambien les dejo mi repositorio con notas y código del curso 👉 UltiRequiem/oop-js-platzi.
Función generadora de números de Fibonacci usando getters y setters.
function FibonacciGenerator(){ this._a = 0; this._b = 1; } FibonacciGenerator.prototype = { get next(){ let c = this._a + this._b; this._a = this._b; this._b = c; return c; }, set nth(number){ if(number<=0 || number>30) console.error("out-bound"); else{ let c = 0; this._a = 0; this._b = 1; while(--number) c = this.next; } } } let fib = new FibonacciGenerator(); fib.nth = 10; //10th fibonacci fib.next; // 89 fib.next; //144 fib.next; //233
Me tomo tiempo entender bien esta clase, pero al final pude organizar los getters y setters, adicional organicé los setters de los atributos que eran arrays, de forma que se puedan insertar y eliminar campos de estos arrays utilizando las funciones ++splice++ y ++push++, espero les sirva esta solución.
class Teacher{ constructor({ id, name, speciality, courses = [], }){ this.id = id; this._name = name; this.speciality = speciality; this._courses = courses; } get name(){ return this._name; } set name(newTeacher){ this._name = newTeacher; } get courses (){ return this._courses; } set courses(newCourse){ for (let i = 0; i < this._courses.length; i++){ if (this._courses[i] === newCourse){ this._courses.splice(i,1); console.log("You have deleted " + newCourse.name + " of " + this._name + " list of Courses"); }else { this._courses.push(newCourse); } } } }
Tienes que exportar cursoProgramacionBasica dentro de main.js. Si es una variable o función, dependiendo de lo que es.
// exporta la función previamente declarada export { myFunction }; // exporta una constante export const foo = Math.sqrt(2);
Luego importas lo que estas exportando dentro del archivo main.js
Ten en cuenta como lo exportas e importas.
EXPORT https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/export IMPORT https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/import
Hola Les comparto mi codigo, el objeto estutdiante tiene la restricción de que el platziRank solo puede recibir number si es tipo "string" mostrará un error.
class Student { constructor({ name, email, username, twitter = undefined, instagram = undefined, approvadesCourses = [], learningPaths = [], platziRank = 0, }) { this.name = name; this.email = email; this.username = username; this.socialMedia = { twitter, instagram, }; this.approvadesCourses = approvadesCourses; this.learningPaths = learningPaths; this._platziRank = platziRank; } get platziRank(){ return this._platziRank(); } set platziRank (newPlatziRank) { if (typeof newPlatziRank === "number"){ this._platziRank = newPlatziRank; } else { console.error("No puedes realizar esta cambio"); } } };