No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

脷ltima oportunidad para asegurar tu aprendizaje por 1 a帽o a precio especial

Antes: $249

Currency
$189/a帽o

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscr铆bete

Termina en:

0D
2H
6M
17S

Module pattern y namespaces: propiedades privadas en JavaScript

13/20
Recursos

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:

  1. Declaramos un objeto privateAtributos en el que colocaremos las propiedades que deseamos que sean privadas y otro objeto publicAtributos en el que queremos que sean p煤blicas. Por ahora, solo name ser谩 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.

  2. 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 ;
    }
    
  3. Finalmente, deber铆amos evitar que el usuario modifique o elimine los m茅todos readName y changeName y dar as铆 mejor seguridad a estos. Con Object.defineProperty haremos 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: "[email protected]", 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)

Aportes 28

Preguntas 11

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

馃挌 Like si te enamoraste de Object.defineProperty con esta clase 馃憡

Existe una manera de definir o modificar varias propiedades a la vez 馃憖. Con la funci贸n Object.defineProperties() se puede pasar un objeto con las propiedades de cada key que quieren ser modificadas:

  // Con defineProperty
  Object.defineProperty(public, "readName", {
    writable: false,
    configurable: false,
  });
  Object.defineProperty(public, "changeName", {
    writable: false,
    configurable: false,
  });

  // Con defineProperties  
  Object.defineProperties(public, {
    readName: {
      configurable: false,
      writable: false,
    },
    changeName: {
      configurable: false,
      writable: false,
    },
  });

Que buen maestro es Timoth茅e Chalamet

Module pattern y namespaces: propiedades privadas en JavaScript

JavaScript no es un lenguaje fuertemente tipado, osea, que no tenemos que definir el tipo de nuestras variables. JavaScript entender谩 que tipo de variable estamos usando.

En javascript no hay una palabra clave para definir una variable privada por lo que podemos crear una funci贸n que nos permita crear esta variable.

Por lo general, podemos usar el Object.defineProperty() para crear la variable publica o privada

Otro forma de lllamar lo que se esta realizando en esta clase es el uso de closures para retornar un contexto controlado y poder usar variables privadas en JS vanilla 馃槃

Todo era felicidad y entusiasmo hasta que llegu茅 a estas 煤ltimas clases y cada vez me empec茅 a perder m谩s 馃槬

actualmente podemos encapsular atributos y metodos privados en JS gracias al ES2022 simplemente agregando un # adelante del nombre de la variable o funcion y estas no entraran en conflicto con los metodos o atributos publicos, facilmente, podriamos tener declarados dos atributos con el mismo nombre y mas aun, una puede contener a la otra y no habra problema alguno, no se si me estoy adelantando pero solo me dio curiosidad jisjis, aqui la ref. 馃挌

Hola! como estan?
Bien, ese pequeno reto del profe para que el usaurio no pueda hacer juan name = 鈥渘icolas鈥, lo resolvi de esta manera:

newName(name) {
            Object.defineProperty(juan, "name", {
                value: name,
                writable: false,
                configurable: true,
                enumerable: true,
            })
        },
        changeName(newName) {
            this.name = newName;
        },

En este punto estoy extremadamente perdido 馃槮

en este caso, object.freeze() no es posible usarlo debido al scope de las funciones

changeName(newName){
        
        const nombre = newName.toLowerCase()
        console.log(nombre)
        for(i in malaPalabras){
            if(nombre.includes(malaPalabras[i].toLowerCase())){
                return console.log(`Esta palabra esta prohibida`)
            }
        }
        this.firsName = newName
    }

ame la terrible palabra 鈥淧ATAAAATAAAAA鈥

Para el reto del profe deja una soluci贸n posible

 function verify(nameVerify){

    let blackList = ["puto","marica","verga","idiota"];
    let verification = true;


    for (ind in blackList){


        if (nameVerify === blackList[ind]){

            verification = false;

            } 

        }
    

        if (verification){

        console.log("Cambio realizado con exito");

        }
        else {

            console.log("El nombre de usuario no esta permitido");
        }

};

Excelente explicaci贸n del profesor

Para poder solucionar lo planteado en el minuto 3:50 (hacer que el nombre no cambie despu茅s), se logra con Object.defineProperty. De esta forma:

changeName(newName){
            this.name = newName;
            Object.defineProperty(this, 'name', {
                writable: false,
            })
        },
//dentro del return de la funci贸n

Para el reto sobre nombres prohibidos, cree un array con la lista de nombres no permitidos.

const noNames = ["nombreProhibido", "nombreProhibido1", "nombreProhibido2"]

Luego simplemente en nuestro metodo changeName, agregamos un condicional, si el newName es alguno de los elementos del array, usando el metodo .includes nos lanzara true y una advertencia, si es false entonces se cambia el nombre.

changeName(newName) {
            if (noNames.includes(newName)) {
                console.warn("Nombre invalido, seleccione otro")
            } else {
                private._name = newName;
            }
        }
function verify(newName){
    const blackList = ["fuck","Bastard","Berk","Knob","Manky","Minger","Pillock"];
    for(ind in blackList){
        if(newName == blackList[ind]){
            return false;
        }else{
            return true;
        }
    }
}

if(verify(newName)){
                _private["_name"];
            }else{
                throw new Error(newName + " no es una palabra permitida >:(");
            }
        },

Wow interesante forma de aplicar programaci贸n orientada a objetos, pero no solo con POO, tambi茅n lo podemos aplicar para nuestro desarrollo en backend o frontend, haciendo m谩s mantenible y legible nuestro c贸digo, aunque sigo prefiriendo la sintaxis de CLASS para POO en javascript

PATATAS!

vuelvo y digo鈥

ACTUALIZEN EL CURSO!!!

La mejor frase.
鈥淓sto nos lleva a diferentes problemas"
o m谩s bien
"A diferentes soluciones鈥

Te explicar茅 el concepto de atributos p煤blicos y privados en JavaScript.
.
En JavaScript, no existe una declaraci贸n expl铆cita para definir atributos como p煤blicos o privados, como en otros lenguajes de programaci贸n. Sin embargo, puedes utilizar convenciones y t茅cnicas para simular atributos privados.
.
Atributos p煤blicos:
Los atributos p煤blicos en JavaScript son aquellos a los que se puede acceder y modificar desde cualquier parte del c贸digo. Se definen directamente en el objeto o funci贸n, sin ning煤n tipo de restricci贸n de acceso.
.
Aqu铆 tienes un ejemplo de un atributo p煤blico en un objeto:

var persona = {
  nombre: "Juan",
  edad: 25
};

console.log(persona.nombre);  // Acceso al atributo p煤blico "nombre"
persona.edad = 30;            // Modificaci贸n del atributo p煤blico "edad"

En este caso, tanto el atributo 鈥渘ombre鈥 como el atributo 鈥渆dad鈥 son accesibles y modificables desde cualquier parte del c贸digo.
.
Atributos privados:
Los atributos privados en JavaScript se simulan mediante convenciones y t茅cnicas para limitar el acceso directo a ellos desde fuera del 谩mbito en el que se definen. No existe una forma nativa de hacerlos privados, pero se pueden utilizar diferentes enfoques para lograrlo.
.
Un enfoque com煤n es utilizar el concepto de clausura (closure) para crear un 谩mbito local y definir los atributos como variables dentro de ese 谩mbito. De esta manera, los atributos solo ser谩n accesibles desde las funciones internas y no desde fuera.
.
Aqu铆 tienes un ejemplo que demuestra c贸mo se pueden crear atributos privados utilizando clausuras:

function crearPersona(nombre) {
  var edad = 25;  // Atributo privado

  // Funci贸n que accede al atributo privado
  function obtenerEdad() {
    return edad;
  }

  // Funci贸n que modifica el atributo privado
  function cambiarEdad(nuevaEdad) {
    edad = nuevaEdad;
  }

  // Objeto que expone solo las funciones p煤blicas
  return {
    nombre: nombre,
    obtenerEdad: obtenerEdad,
    cambiarEdad: cambiarEdad
  };
}

var persona = crearPersona("Juan");
console.log(persona.nombre);           // Acceso al atributo p煤blico "nombre"
console.log(persona.obtenerEdad());    // Acceso al atributo privado "edad"
persona.cambiarEdad(30);                // Modificaci贸n del atributo privado "edad"
console.log(persona.obtenerEdad());    // Acceso al atributo privado "edad" modificado

En este ejemplo, utilizamos una funci贸n llamada crearPersona para crear un objeto que encapsula tanto atributos privados como p煤blicos. La variable edad se define dentro de la funci贸n y, por lo tanto, solo es accesible desde las funciones internas (obtenerEdad y cambiarEdad). El objeto devuelto por crearPersona solo expone las funciones p煤blicas (nombre, obtenerEdad y cambiarEdad), lo que permite acceder a los atributos privados de manera controlada.
.
Aunque estos atributos no son estrictamente privados en el sentido tradicional, el uso de clausuras y t茅cnicas similares nos permite ocultarlos y controlar el acceso a ellos.
.
Espero que esta explicaci贸n te ayude a entender c贸mo se pueden crear atributos p煤blicos y privados en JavaScript. Si tienes m谩s preguntas, no dudes en hacerlas.

Patatas 馃が馃が馃が

Mi resumen:

// ### Evitar modificaciones en atributos de objetos

/*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:*/

function createStudent3({
    name,
    age
} = {}) {
    const privateAttributes = { //m茅todos privados
        "_name" : name,
    }
    const publicAttributes = {//lo que se podr谩 ver y manipular
        age,
        readName(){
            return privateAttributes["_name"];
        },
        changeName(param) {
            privateAttributes["_name"] = param;
        }
    }
    return publicAttributes;
}

const alfonso = createStudent3({name : "alfonso",age : 14});

console.log(alfonso);
/*
{
    age: 14,
    readName: [Function: readName],
    changeName: [Function: changeName]
}
*/
console.log(alfonso.readName()); //alfonso
alfonso.changeName("alfonsito"); //alfonso //solo a trav茅s del m茅todo changeName es posible cambiar el nombre, ya que no es posible hacerlo de manera directa
alfonso._name = "GOKU"; //No cambiar谩 de nombre
console.log(alfonso.readName()); //alfonsito

//Sin embargo si lo dejamos as铆, se podr谩 modificar el valor de m茅todos, por lo que se usar谩 Object.defineProperty() para evitar ello

Object.defineProperty(alfonso,"readName",{
    writable : false,
    configurable : false
})
Object.defineProperty(alfonso,"changeName",{
    writable : false,
    configurable : false
})

console.log(Object.getOwnPropertyDescriptors(alfonso));

/*
{
    age: { value: 14, writable: true, enumerable: true, configurable: true },
    readName: {
        value: [Function: readName],
        writable: false,
        enumerable: true,
        configurable: false
    },
    changeName: {
        value: [Function: changeName],
        writable: false,
        enumerable: true,
        configurable: false
    },
    _name: {
        value: 'GOKU',
        writable: true,
        enumerable: true,
        configurable: true
    }
}
*/

Con cada cosa nueva que veo de Javascript me hace desear m谩s el momento de llegar a aprender Typescript.

Hoal! Este es mi codigo para poder firzar el retorno del objeto!

const isObject = (object) => {
    return typeof object == "object"
}//es un array o un objeto


function deepFreeze(obj) {

    for (key in obj) {
        let keyIsObject = isObject(obj[key])

        if(keyIsObject) {
             deepFreeze(obj[key])
        } else {
            Object.freeze(obj[key])
        }
    }

    return Object.freeze(obj)

}



function user({
    name, 
    contactInfo = requiredParam('contactInfo'), //parametro por defecto. Si no le paso el contactInfo, llamare a la fn contactInfo y retornara un error
    active = true,
    apellido,
    cursos = []
    } = {} )
    {
    


    return deepFreeze({
        name,
        contactInfo,
        addCourse(course) {
            this.cursos.push(course)
        },
        changeName(newName) {
            this.name = newName
        },
        active,
        apellido,
        cursos
    })


}