Encapsulamiento en JavaScript: Propiedades Privadas y Públicas
Clase 13 de 20 • Curso Intermedio de Programación Orientada a Objetos en JavaScript
Contenido del curso
Profundicemos en los objetos
Cómo copiar objetos en JavaScript
Recursividad en JavaScript
Abstracción y encapsulamiento sin prototipos
- 11

Creación de Fábricas de Objetos con Patron RORO en JavaScript
18:52 min - 12

Abstracción y Encapsulamiento en JavaScript Sin Prototipos ni Clases
12:58 min - 13

Encapsulamiento en JavaScript: Propiedades Privadas y Públicas
Viendo ahora - 14

Getters y Setters en JavaScript: Protección y Validación de Propiedades
09:40 min
Cómo identificar objetos
- 15

Duck Typing en JavaScript: Identificación de Objetos y Tipos
05:30 min - 16

Validación de Propiedades en Objetos JavaScript
14:22 min - 17

Validación de Instancias y Prototipos en JavaScript
17:45 min - 18

Protección de Propiedades Privadas en Prototipos JavaScript
15:10 min - 19

Métodos Estáticos en JavaScript: Creación de SuperObject
07:52 min
Próximos pasos
En JavaScript no tenemos keywords para indicar que un atributo es privado o público a diferencia de otros lenguajes de programación. Sin embargo, podemos aplicar ciertas técnicas y métodos para lograrlo.
Atributos públicos y privados en JavaScript
Modificaremos la función creada anteriormente con la que podíamos generar nuevos objetos. Esto con la finalidad de separar los atributos que queremos que sean privados (por ahora solo el atributo name) y públicos, además de crear 2 funciones: una para poder modificar el atributo privado y otra para obtener el valor de esa propiedad privada:
-
Declaramos un objeto
privateAtributosen el que colocaremos las propiedades que deseamos que sean privadas y otro objetopublicAtributosen el que queremos que sean públicas. Por ahora, solonameserá privada y por convención se coloca un guion bajo delante del nombre de aquel atributo privado:function isObject(subject) { return typeof subject == "object"; } function isArray(subject) { return Array.isArray(subject); } function requiredParam(param) { throw new Error(param + " es obligatorio"); } function createStudent({ name = requiredParam("name"), email = requiredParam("email"), age, twitter, instagram, facebook, approvedCourses = [], learningPaths = [], } = {}) { const privateAtributos = { // 👈👈 // '_name' es el atributo privado // 'name' es el parámetro que recibe la función "_name": name, }; const publicAtributos = { // 👈👈 // El resto de atributos serán públicos: email, age, approvedCourses, learningPaths, socialMedia: { twitter, instagram, facebook, } } return publicAtributos ; }Por consiguiente, solo retornaremos
publicAtributos, pues contiene las propiedades a las que sí podrán acceder los usuarios. -
Crearemos las funciones con las que el usuario puede editar y leer el valor del atributo privado
_name:function isObject(subject) { return typeof subject == "object"; } function isArray(subject) { return Array.isArray(subject); } function requiredParam(param) { throw new Error(param + " es obligatorio"); } function createStudent({ name = requiredParam("name"), email = requiredParam("email"), age, twitter, instagram, facebook, approvedCourses = [], learningPaths = [], } = {}) { const privateAtributos = { "_name": name, } const publicAtributos = { // El resto de atributos serán públicos: email, age, approvedCourses, learningPaths, socialMedia: { twitter, instagram, facebook, }, readName() { // 👈👈 return privateAtributos["_name"]; }, changeName(newName) { // 👈👈 privateAtributos["_name"] = newName; }, } return publicAtributos ; } -
Finalmente, deberíamos evitar que el usuario modifique o elimine los métodos
readNameychangeNamey dar así mejor seguridad a estos. ConObject.definePropertyharemos las configuraciones respectivas para evitar lo mencionado:function isObject(subject) { return typeof subject == "object"; } function isArray(subject) { return Array.isArray(subject); } function requiredParam(param) { throw new Error(param + " es obligatorio"); } function createStudent({ name = requiredParam("name"), email = requiredParam("email"), age, twitter, instagram, facebook, approvedCourses = [], learningPaths = [], } = {}) { const privateAtributos = { "_name": name, }; const publicAtributos = { // El resto de atributos serán públicos: email, age, approvedCourses, learningPaths, socialMedia: { twitter, instagram, facebook, }, readName() { return privateAtributos["_name"]; }, changeName(newName) { privateAtributos["_name"] = newName; }, }; Object.defineProperty(publicAtributos, "readName", { // 👈👈 writable: false, configurable: false, }); Object.defineProperty(publicAtributos, "changeName", { // 👈👈 writable: false, configurable: false, }); return publicAtributos ; } // Creamos un nuevo objeto const juan = createStudent({ email: "juanito@frijoles.co", name: "Juanito" }); // Intentamos eliminar y alterar los métodos changeName y readName delete juan.changeName; // false delete juan.readName; // false juan.changeName = function (nombreImpostor) { // NO se ve afectada la función original return "patatas"; }La desventaja de protegerlos es que no nos permitiría trabajar con el polimorfismo (uno de los pilares de POO).
El funcionamiento de nuestros métodos generados changeName y readName es muy similar a los Getters y Setters. Veamos cómo aplicar estos en JavaScript. 🤔💪
Contribución creada por: Martín Álvarez (Platzi Contributor)