No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Getters y setters en JavaScript

12/20
Recursos

¿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:

  • Getters: Permiten acceder a los valores de propiedades encapsuladas.
  • Setters: Facilitan la modificación de dichos valores, permitiendo agregar lógica adicional, como validaciones, antes de realizar cambios.
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:

  1. Describe cómo se utilizan getters y setters sin la sintaxis de clases: Comprende cómo trabajar con ellos en prototipos tradicionales de JavaScript.
  2. Aplica getters y setters en un proyecto propio: Actualiza atributos dentro de un sistema más complejo (como un clon de una aplicación educativa) para gestionar estudiantes y cursos.

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.

Aportes 90

Preguntas 18

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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;
    }
  }
}

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.

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

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?

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.

  • Getters se usan para acceder a las propiedades en un objeto.

  • Setters para cambiar or silenciar una propiedad en un objeto

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

Los getters y setters son construcciones de los objetos que permiten acceder a valores del mismo sin revelar la forma de su implementación.

Hackeado 😎😎

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);
            }
            
        }
                   
    }
}

Holas les comparto parte de mi código 😃

muy interesante las clases he aprendido bastante

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

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

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;
        }
    }   
}

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");
        }
    }
};

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;
        }
    }

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

Yo protegí el cambio de nombre con una contraseña

class Course {
  constructor({
    name,
    calsses = []
  }) {
    // Al agregarle el _ (guión bajo) ocultamos el atributo name
    this._name = name;
    this.calsses = calsses;

  }

  get name() {
    return this._name;
  }

  set name(nuevoNombre) {
    if (nuevoNombre === "") {
      console.error("Error: Debes de ponerle un nombre al curso")

    } else {
      let contraseñaCurso = prompt("Introduce la contraseña:");
      if (contraseñaCurso === 'password') {
        this._name = nuevoNombre;
      } else {

        console.error("Error: No tienes permiso para cambiar el nombre del curso!")
      }
    }
  }

}

Para utilizar getter o setter fuera de clases conseguí en al documentación que se utiliza un método estático.

El método estático Object.defineProperty() define una nueva propiedad sobre un objeto, o modifica una ya existente, y devuelve el objeto modificado.

tiene la siguiente sintaxis :
-Object.defineProperty(obj, prop, descriptor)

Este método nos permite modificar el comportamiento por defecto de las propiedades. Es decir, nos permite definir una propiedad como no enumerable, no modificable o incluso evitar que pueda ser eliminada del objeto

dejo el enlace por si quieren profundizar mas en el tema

https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

📌 Los getters y setters sirven para definir los Accessors, es decir, permiten modificar el funcionamiento de acceso para obtener los valores de las propiedades de los objetos.

En JavaScript, los setters y getters son métodos especiales que te permiten controlar el acceso y la modificación de propiedades de un objeto. Aunque la sintaxis de clases ofrece una forma más declarativa de crear setters y getters, también puedes utilizar prototipos para lograr el mismo resultado. Aquí te muestro cómo hacerlo:


function Persona(nombre, edad) {
  this._nombre = nombre;
  this._edad = edad;
}

Persona.prototype = {
  // Getter para obtener el nombre
  get nombre() {
    return this._nombre;
  },

  // Setter para establecer el nombre
  set nombre(nuevoNombre) {
    this._nombre = nuevoNombre;
  },

  // Getter para obtener la edad
  get edad() {
    return this._edad;
  },

  // Setter para establecer la edad
  set edad(nuevaEdad) {
    if (nuevaEdad >= 0) {
      this._edad = nuevaEdad;
    } else {
      console.log("La edad no puede ser un valor negativo.");
    }
  }
};

// Crear una instancia de Persona
var persona = new Persona("Juan", 25);

// Utilizar los setters y getters
console.log(persona.nombre);  // Output: Juan
console.log(persona.edad);    // Output: 25

persona.nombre = "Pedro";
persona.edad = 30;

console.log(persona.nombre);  // Output: Pedro
console.log(persona.edad);    // Output: 30


En el ejemplo anterior, creamos un constructor Persona y definimos los getters y setters utilizando la propiedad prototype del constructor. Cada getter tiene el mismo nombre que la propiedad a la que accede, mientras que cada setter tiene el mismo nombre pero precedido por la palabra clave set.

Al utilizar los getters, podemos obtener los valores de las propiedades _nombre y _edad. Por otro lado, al utilizar los setters, podemos modificar los valores de estas propiedades. En el caso del setter de edad, hemos agregado una validación para asegurarnos de que la edad no sea un valor negativo.

La finalidad de poner un underline antes del atributo, no es que lo haga privado, si no cuando invoquen ese atributo al no empezar por la letra, no puedan cambiaro obtener el valor direcro del atributo, sin embargo sigue visible, en cambio cuando invocan por la primer letra del atributo a quien llaman es al set o get del atributo, y ya con metodos podemos hacer distintas validaciones antes de asignarle el valor al atributo local o obtener la informacion de su valor
Aca les comparto un ejemplo donde el id 0 no cuenta como id valido para las rutas de aprendizaje

LearningPath

export default class LearningPath {
    constructor({
      id,
      title,
      courses = [],
    }) {
      this._id = id;
      this._title = title;
      this._courses = courses;
      this.coursesQuantity = courses.length;
    }

    get id(){
      return this._id;
    }

    set id(newId){
      if(newId === 0){
        console.log("El id " + newId + " no cuenta como indice de LearningPath")
      }
      this._id = newId;
    }

Main

import LearningPath from './LearningPath.js'

const escuelaDesarrolloWeb = new LearningPath({
  id: 3,
  title: 'Escuela de Desarrollo Web',
  courses: [cursoProgramacionBasica],
});
console.log(escuelaDesarrolloWeb);
escuelaDesarrolloWeb.id=0

Hay dos tipos de propiedades de un objeto.
.

  • Propiedad de datos
  • Propiedades de acceso (accessors)

Estas propiedades son funciones que se ejecutan para obtener (get) y asignar (set) un valor, pero que para un código externo se ven como propiedades normales.

Les dejo una documentación para que lo puedan ver también con objetos literales y otros ejemplos.

Documentación: "Getters y “setters” - javascript.info/property-accessors

Acá comparto una validación para el correo, claramente puede ser mayor. Espero les sirva.

Por ahi vi que en typescript si es posible agregar private, public and protected

Reto 1:

function sintaxProto(param1, param2) {
    this._param1 = param1;
    this._param2 = param2;
}
sintaxProto.prototype = {
    get param1() {
        return this._param1;
    },
    set param1(newParam) {
        this._param1 = newParam;
    },
    get param2() {
        return this._param2;
    },
    set param2(newParam) {
        this._param2 = newParam;
    },
}

Reto 2:

class Student {
    constructor({
        name,
        email,
        username,
        twitter = undefined,
        instagram = undefined,
        facebook = undefined,
        approvedCourses = [],
        learningPaths = [],
    }){
        this._name = name;
        this._email = email;
        this._username = username;
        this._socialMedia = {
            twitter,
            instagram,
            facebook,
        };
        this._approvedCourses = approvedCourses;
        this._learningPaths = learningPaths;
    }

    get name() { return this._name; }
    set name(newname) { this._name = newname; }

    get email() { return this._email; }
    set email(newemail) { this._email = newemail; }

    get username() { return this._username; }
    set username(newusername) { this._username = newusername; }
    
    get socialMedia() { return this._socialMedia; }
    set socialMedia(newSocialMedia) { this._socialMedia = newSocialMedia; }
    
    get approvedCourses() { return this._approvedCourses; }
    set approvedCourses(newApprovedCourses) { this._approvedCourses = newApprovedCourses; }
    
    get learningPaths() { return this._learningPaths; }
    set learningPaths(newLearningPaths) { this._learningPaths = newLearningPaths; }
}

class approvedCourses {
    constructor({
        name,
        courses = [],
        calificacion,
    }){
        this._name = name;
        this._courses = courses;
        this._calificacion = calificacion;
    }

    get name() { return this._name; }
    set name(newName) { this._name = newName; }

    get courses() { return this._courses; }
    set courses(newCurses) { this._courses = newCurses; }

    get calificacion() { return this._calificacion; }
    set calificacion(newCalificacion) { this._calificacion = newCalificacion; }
}
class Clases {
    constructor({
        name,
        recursos = [],
        comentarios = [],
    }){
        this._name = name;
        this._recursos = recursos; 
        this._comentarios = comentarios; 
    }

    get name() { return this._name; }
    set name(newName) { this._name = newName; }

    get recursos() { return this._recursos; }
    set recursos(newRecursos) { this._recursos = newRecursos; }

    get comentarios() { return this._name; }
    set comentarios(newComentarios) { this._comentarios = newComentarios; }
}
class Comentario {
    constructor({
        student,
        fecha,
        texto,
        tipo, //pregunta o aporte
        comentRespuesta = [], //Comentarios respuestas
    }){
        this._student = student;
        this._fecha = fecha; 
        this._texto = texto; 
        this._tipo = tipo; 
        this._comentRespuesta = comentRespuesta; 
    }

    get student() { return this._student; }
    set student(newStudent) { this._student = newStudent; }

    get fecha() { return this._fecha; }
    set fecha(newFecha) { this._fecha = newFecha; }

    get texto() { return this._texto; }
    set texto(newTexto) { this._texto = newTexto; }

    get tipo() { return this._tipo; }
    set tipo(newTipo) { this._tipo = newTipo; }

    get comentRespuesta() { return this._comentRespuesta; }
    set comentRespuesta(newComentRespuesta) { this._comentRespuesta = newComentRespuesta; }
}

class Course {
    constructor({
        name,
        clases = [],
    }){
        this._name = name; 
        this._clases = clases; 
    }
    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;
        }
    }

    get clases() { return this._clases; }
    set clases(newClases) { this._clases = newClases; }
}

class LearningPaths {
    constructor({
        name,
        courses = [],
    }){
        this._name = name;
        this._courses = courses;
    }

    get name() { return this._name; }
    set name(newName) { this._name = newName; }

    get courses() { return this._courses; }
    set courses(newCourses) { this._courses = newCourses; }
}
// Reto: creando getter y setter en objetos de prototipos
function Course2({ name, clases = [] }) {
    this._name = name;
    this.clases = clases;
}

Course2.prototype.getName = function() {
    return this._name;
}

Course2.prototype.setName = function (newName) {
    if (newName === 'Nombre Malicioso') {
        console.error('Este nombre no está permitido');
    } else {
        return this._name = newName;
    }
}

const courseProgrBasica2 = new Course2({
    name: 'Prograamción Básica',
});

console.log(courseProgrBasica2.getName());
courseProgrBasica2.setName('Otro Curso');
console.log(courseProgrBasica2.getName());

Tengo entendido que en ECMAScript 5 definimos Getters y Setters con el método defineProperties del objeto Object.

Aquí les coloco un ejemplo con el prototipo de Courses:


// Definimos una clase llamada Course e inicializamos sus atributos
function Course({ name, classes = [] }) {
  this.name = name;
  this.classes = classes;
}

// Usamos Object.defineProperty para agregar propiedades a un objeto
// El primer parámetro hace referencia al objeto al que se le agregará la propiedad
// El segundo parámetro es el nombre de la propiedad
// El tercer parámetro es un objeto con las propiedades de la propiedad,
// En este caso definimos un get y un set como en la clase
Object.defineProperty(Course.prototype, "name", {
  get: function () {
    return this._name;
  },

  set: function (value) {
    this._name = value;
  },
});

// Inicializamos una instancia del objeto
const ReactCourse = new Course({
  name: "React",
  classes: [
    {
      name: "React Basics",
      description: "Learn the basics of React",
      duration: "1 hour",
      date: "2020-01-01",
    },
    {
      name: "React Hooks",
      description: "Learn the basics of React Hooks",
      duration: "1 hour",
      date: "2020-01-01",
    },
  ],
});

// Luego usamos los metodos get y set, para editar y leer la propiedad name
ReactCourse.name = "New React Name"
console.log(ReactCourse.name)

Happy coding 😄

<code> 

// clase
class User{
    constructor({
        name,
        age,
        nationality
    }){
        this._name = name;
        this._age = age;
        this.nationality = nationality;
    }

    // get
    get name(){
        return this._name;
    }
    // set
    set name(nuevoName){
        if (nuevoName === "") {
            console.error("Hey introduce un nombre")
        } else {
            this._name = nuevoName;
        }
    }

    // get
    get age(){
        return this._age;
    }
    // set
    set age(nuevoAge){
        if (nuevoAge === "") {
            console.error("Hey introduce una edad")
        } else {
            this._age = nuevoAge;
        }
    }
}

const usuario = new User({
    name: "Hacker02",
    age: 24,
    nationality: "Perú"
})

Getter y Setter en Protipos

<code> 
function Teacher(name) {
    this._nombre = name
}

Teacher.prototype = {
    // Get
    get name (){
        return this._nombre;
    },
    // set
    set name(otherName){
        if (otherName === "") {
            console.error("Profesor... su nombre")
        } else {
            this._nombre = otherName;
        }
    }
}

const Profesor = new Teacher("alejandro")

![](

En JavaScript, los getters y setters también se pueden utilizar con prototipos, sin necesidad de utilizar la sintaxis de clases de JavaScript. En lugar de definir un getter o setter utilizando la sintaxis de clase, se pueden definir como métodos de un objeto prototipo.

Los GETTERS y SETTERS son un peaje:

Te dejan psar, pero primero pasa por ellos.

Estas es mi solución al reto:

function Student(name, age, naationality, nameOfMom ){

    this._name = name;
    this.age = age;
    this.naationality = naationality;
    this.nameOfMom = nameOfMom;

   
}

Student.prototype = {
    get name(){
        return this._name;
    },
    set name(newName){
        this._name = newName;
    }
}
<code> 

En respuesta a reto 1:

function Name() {
	constructor({
	name,
	lastName,}) {
	this.name = name;
	this.lastName = lastName}
}

Name.prototype = {
	get fullName(){
	return this.name + ' ' + this.lastName;
	}

	set fullName(newName, newLastName){
	this.name = newName;
	this.lastName = newLastName;
	}
}

//se emplea la sintaxis "antigua" de JavaScript, accediendo a la "función" como prototipo y definiendo sus métodos get y set, además accediendo a las variables del prototipo sin comillas francesas, siendo implementadas en ES6 (2015) como forma de evitar la concatenación y emplear la forma ${}.

Aqui dejo el reto:

class Student{
    constructor({
        username,
        password,
        name,
        email,
        nacionality,
        twitter = undefined,
        instagram = undefined,
        facebook = undefined,
        subscription = "free",
        coursesAproved = [],
        learningPaths = [],
        portfolio,
        tutorials,
        
    }){
        this._username = username
        this._password = password
        this.name = name
        this.email = email
        this.nacionality = nacionality
        this.socialMedia = {
            twitter,
            instagram,
            facebook,
        } 
        this.subscription = subscription
        this.coursesAproved = coursesAproved
        this.learningPaths = learningPaths
        this.portfolio = portfolio
        this.tutorials = tutorials
    }

    get username(){
        this._username
    }

    set username(newUsername){
        this._username = newUsername
    }

    get password(){
        this._password
    }

    set password(newPassword){
        this._password = newPassword
    }
}
/*
Implementación de encapsulamiento en el año 2022 con base al ejemplo dado por el profe
*/
class Course{
    #courseName;
    #nombresNoPermitidos;
    constructor({
        courseName,
        classes = [],
        nombresNoPermitidos = []
    }){
        this.#courseName = courseName;
        this.classes = classes;
        this.#nombresNoPermitidos = nombresNoPermitidos;
    }
    get courseName(){
        return this.#courseName;
    }
    set courseName(newCourseName){
        let cont = 0;
        for(let k = 0; k < this.#nombresNoPermitidos.length; k++){
            let nameLocked = this.#nombresNoPermitidos[k];
            if(nameLocked.toLowerCase() === newCourseName.toLowerCase()){
                ++cont;
                console.error("Error!! el nombre " + newCourseName + " no está permitido");
                break;
            }
        }

        if(cont == 0){
            this.#courseName = newCourseName;
        }
        
    }
    addClass(clase){
        this.classes.push(clase);
    }
    toString(){
        let mensaje = `nombre del curso: ${this.courseName}`;
        if(this.classes.length > 0){
            this.classes.forEach(clase => mensaje += 				`\r\n${clase.toString()}`);
        }
        return mensaje;
    }
}

Aquí tengo algunos otros métodos de mas como el de escribir la información de mi instancia.
 

class Class{
  constructor({
    nameClass,
    video = "No tiene",
    resources = "No tiene",
  }){
    this.nameClass = nameClass
    this.video = video
    this.resources = resources
  }
  get sayInfoClass(){
    console.log(`Nombre de clase es: ${this.nameClass} video: ${this.video} recursos: ${this.resources}`);
  }
  get getClass(){
    return this
  }
}

class Courses{
  constructor({
    nameCourse,
    classes = [],
  }){
    this._nameCourse = nameCourse
    this.classes = classes
  }
  get nameCourse(){
    return this._nameCourse;
  }
  set changeName (newCourse){
    if (newCourse == "Curso Malito de Programacion Basica"){
      console.error("Web... no");
    }else{
      this._nameCourse = newCourse;
    }
  }

  set addClass(newClass){
    this.classes.push(newClass);
  }
  set deleteCourses(deleteClasses){
    this.classes = this.classes.filter(classes =>  classes != deleteClasses)    
  }
  get sayClasses(){
    let result = "";
    this.classes.forEach(classe => {
        result +=`${classe.nameClass} - `
    });
    console.log(result);        
  }
  get getClasses(){
    return this.classes
  }
}

class LearningPath {
  constructor({
    nameLearningPath,
    courses = []
  }){
      this.nameLearningPath = nameLearningPath;
      this.courses = courses;
  }
  set addCourse(newCourse){
      this.courses.push(newCourse);
  }
  set deleteCourses(deleteCourse){
    this.courses = this.courses.filter(course =>  course != deleteCourse)    
  }
  get sayCourses(){
    let result = "";
    this.courses.forEach(course => {
        result +=`${course.nameCourse} - `
    });
    console.log(result);        
  }
  get getCourses(){
    return this.courses
  }
}

class Student {
  constructor({
        name,
        email,
        username,
        twitter = undefined,
        instagram = undefined,
        facebook = undefined,
        approvedCourses = [],
        learningPaths = [],
    }){
    this.name = name;
    this.email = email;
    this.username = username;
    this.socialMedia = {
      twitter,
      instagram,
      facebook,
    };
    this.approvedCourses = approvedCourses;
    this.learningPaths = learningPaths;
    }

    set addLearningPaths(newLearningPaths){
        this.learningPaths.push(newLearningPaths)        
    }

    set deleteLearningPaths(deleteLearningPath){
        this.learningPaths = this.learningPaths.filter(item => item != deleteLearningPath)

    }
    get sayLearningPaths(){
        let result = "";
        this.learningPaths.forEach(nameLearningPath => {
            result +=`${nameLearningPath.nameLearningPath} - `
        });
        console.log(result);        
    }
    get getLearningPaths(){
      return this.learningPaths
    }
}

// CREACION DE CLASES
const clase1 = new Class({
  nameClass:'Clases en javascript',
  video:'https://platzi.com/clases/2332-javascript-poo/38621-clases-en-javascript/'
})
const clase2 = new Class({
  nameClass:'Ventajas de la programación orientada a objetos',
  video:'https://platzi.com/clases/2332-javascript-poo/38622-ventajas-de-la-programacion-orientada-a-objetos/'
})
const clase3 = new Class({
  nameClass:'Que es Abstracion',
  video:'https://platzi.com/clases/2332-javascript-poo/38623-que-es-abstraccion/'
})
const clase4 = new Class({
  nameClass:'Abstracion',
  video:'https://platzi.com/clases/2332-javascript-poo/38624-abstraccion-en-javascript/'
})

// CREACION DE CURSOS
const cursoProgramacionBasica = new Courses({
  nameCourse:"Curso Gratis de Programacion Basica",
  classes:[
    clase1,
    clase2
  ]
})
const cursoDefinitivoHTML = new Courses({
  nameCourse:"Curso Definitivo de HTML y CSS",  
  classes:[
    clase1,
    clase3
  ]
})
const cursoPracticoHTML = new Courses({
  nameCourse:"Curso Practico de HTML y CSS",  
  classes:[
    clase1,
    clase4
  ]
})
const cursoBasicoPOO = new Courses({
  nameCourse:"Curso Gratis de Programacion Basica",
  classes:[
    clase2,
    clase3
  ]
})
const cursoBasicoJsPOO = new Courses({
  nameCourse:"Curso Gratis de Programacion Basica",
  classes:[
    clase3,
    clase4
  ]
})

// CREACION DE ESCUELAS
const escuelaWeb = new LearningPath({ 
  nameLearningPath : "Escuela de desarrollo web",
  courses:[
    cursoProgramacionBasica,
    cursoDefinitivoHTML,
    cursoPracticoHTML]
});
const escuelaJs = new LearningPath({ 
  nameLearningPath : "Escuela de desarrollo web",
  courses:[
    cursoPracticoHTML,
    cursoBasicoPOO,
    cursoBasicoJsPOO]
});

// CREACION DE ESTUDIANTES
const juanStudent = new Student({
  name: "JuanDC",
  username: "juandc",
  email: "[email protected]",
  twitter: "fjuandc",
  learningPaths: [
    escuelaWeb,
  ],
});


const miguelitoStudent = new Student({
  name: "Miguelito",
  username: "migelitofeliz",
  email: "[email protected]",
  instagram: "migelito_feliz",
  learningPaths: [
    escuelaWeb,
    escuelaJs
  ],
});

<code> 
class Course {
    constructor({
        name,
        classes = [],
    }){
        this._name = name;
        this.classes = classes;
    }

    get name (){
        return this._name;
    }

    set name(nuevoNombrecito){
        if(nuevoNombrecito === "Curso Malito de Programacion"){
            console.error ("web .... no response");
        }else{
            this._name = "nuevoNombrecito";
        }
         
        
    }

};



const cursoProgBasica = new Course({
    name: "Curso de Programacion Basica Gratis",
    classes:[
            ClaseDeComputacion    ]

});

cursoProgBasica.name = "Curso de Programacion Basica Gratis"; 

si acceden a la consola para correrlo no se puede cambiar el nombre "nuevoNombrecito " con el metodo que indica en clase , pero si accedemos con la opcion ._name = “y si intenta cambiar el nombre , este se registrara e incluso cambiara el que pusimos en console.error.” . pero si lo ponemos sin ser string, se deja pasar los cambios como la clase que se muestra, me parecio interesante este experimento porque el codigo se cambia rapidamente su comportamiento por un solo dato, que pueden parecer similar.

Dejo mis apuntes del curso con notas, interpretaciones y ejemplos;

https://www.notion.so/Curso-B-sico-POO-JS-8b1ae724db364a06b5cac3055526c7b1

function Studentt (name, age, cursosAprobados) {
    this._name = name;
    this.age  = age;
    this.cursosAprobados = cursosAprobados;
    // this.aprobarCurso = function (nuevoCurso) {
    //     this.cursosAprobados.push(nuevoCurso); 
    // }
}

Studentt.prototype.aprobarCurso = function (nuevoCurso) {
    this.cursosAprobados.push(nuevoCurso);
}


Studentt.prototype = {

    get name() {
        return this._name;
    },

    set name(name) {
        this._name = name;
    }
}


const mateo = new Studentt('Mateo', 25, ["Programacion web"])

la clase escrita como funcion:

function courseForFunction(name , clases=[]){
    let saveName =  name ;
    let saveClases = clases;
    return {
        getName:()=>{
            return saveName;
        },
        setName:(newName)=>{
            saveName =  newName;
        },
        getClases:()=>{return saveClases},
        setClases:(variable)=>{saveClases=variable},

    }
    
}

:0 no sabia lo de console.error :0

mientras llenaba mi app me dio flojera escribir los getters y setters y como no encontre todavia un plugin que los haga con estas dos funciones los puedes cocechar por console.log( )


function firstToUpper(texto){
    segunda = texto.slice(1);
    primera =  texto.charAt(0);
    formatoDeseado = primera.toUpperCase() + segunda;
    return  formatoDeseado;    
}

function getAndSet(arr){
devolver ='';
for(let i =0; i<arr.length ; i++){
parametro = arr[0];


newParametro =  firstToUpper(parametro);
devolver +=   
`get ${parametro}(){return this._${parametro};}
set ${parametro}(new${newParametro}){
        this._${parametro} = new${newParametro}
    }
`
}//fin for
console.log( devolver );
}

Hice el proyecto a mi manera para practicar los distintos conceptos , me quedo asi:

Lo quise hacer con clases, impidiendo que las las rutas de aprendizaje no se puedan cambiar a categorías no existentes. Si se quisiera limitar a que la ruta “Escuela de desarrollo web” no pueda cambiarse a ninguna otra categoría, se debe de implementar encapsulamiento en la clase “Escuela de sarrollo web” o el nombre que se le de para poner las condicionales en la ruta de aprendizaje

class LearningPath {
    constructor({category = [], name, courses = []}){
        this._category = category;
        this.name = name;
        this.courses = courses;
    }

    get category(){
        return this._category;
    }

    set category(newCategory){
        if(newCategory !== ["Desarrollo e Ingeniería", "Inglés", "Negocios y Emprendimiento", "Marketing Digital", "Habilidades Blandas", "Startups"]){
            console.error("That's not an accepted category")
        } else {
            this._category = newCategory;
        }
    }
}

const desarrolloWeb = new LearningPath({
    category: "Desarrollo e Ingeniería",
    name: "Escuela de desarrollo web",
    courses: ["Curso básico de computación", "Curso de HTML Y CSS", "Curso de POO"]
})

si va mi código 😄

class Student {
constructor({
name,
email,
twitter = undefined,
instagram = undefined,
approvedCourses= [],
learningPaths= [],
}){
this.name=name;
this.email=email;
this.socialMedia= {
twitter,
instagram,
};
this.approvedCourses=approvedCourses;
this.learningPaths=learningPaths;
}
};

class LearningPaths {
constructor({name,courses=[]}){
this._name=name;
this.courses=courses;
}
get name(){
return this._name
}
set name(nuevoNombre){
if(nuevoNombre===“curso malo”){
console.error(“wey…no”)
}else{
this._name= nuevoNombre;
}
}
}

class Student3 {
    constructor({
        name,
        email,
        username,
        twitter = undefined,
        instagram = undefined,
        approvedCourses = [],
        learningPaths = [],
    }) {
        this.name = name;
        this.myEmail = email;
        this.username = username;
        this.socialMedia = {
            twitter,
            instagram,
        };
        this.approvedCourses = approvedCourses;
        this.learningPaths = learningPaths;
    }
    get email() {
        return this.myEmail;
    }
    set email(newEmail) {
        if(newEmail !== this.myEmail) {
            console.error("You cannot change the email")
        } else {
            this.myEmail = newEmail;
        }
    }
}

//Instance
const john = new Student3({
    name: "JuanDC",
    username: "Juarg14",
    email: "[email protected]",
    twitter: "juan51",
    learningPaths: webDevelopment,
});

john.email = "[email protected]";

La primera vez que vi esto fue leyendo la documentacion de Typescript, les admito que fue un concepto que se me dificulto mucho terminar de aprenderlo.

Pero tiene ventajas muy marcadas, no solo proteger con el encapsulamiento, sino tambien aplicar logica de programacion a atributos que queremos proteger.

Asi es como usaria los getters y setters sin la sintaxis de clases:

function prototipo(var1, var2){
    this._var1 = var1;
    this.var2 = var2;
    this.GetVar1 = function (){
        return this._var1;
    }
    this.SetVar1 = function (var1){
        this._var1 = var1;
    }
}

const prototipo1 = new prototipo(5,10);

y estos son los getters y setters que agregue al codigo:

//cursos
class Course {
    constructor({
        name,
        classes = [],
        test,
    }){
        this._name = name;
        this.classes = classes;
        this.test= test;
    }
    get name(){
        return this._name;
    }
    set name(name){
        if(name === "Nombre feo"){
            console.error("Wey... no");
        }else{
        this._name = name;
        }
    }
}
//clases
class clases{
    constructor({
        name,
    }){
        this._name = name;
    }
    get name(){
        return this._name;
    }
    set name(name){
        this._name = name;
    }
}
//tests
class tests{
    constructor({
        name,
        score = 0,
        passed = false,
    }){
        this._name = name;
        this._score = score;
        this._passed = passed;
    }
    get name(){
        return this._name;
    }
    set name(name){
        this._name = name;
    }
    get score(){
        return this._score;
    }
    set score(score){
        this._score = score;
    }
    get passed(){
        return this._passed;
    }
    set passed(score){
        if(score >= 90){
            this._passed = true;
        }
        else{
            this._passed = false;
        }
    }
}
//learningpaths
class LearningPath{
    constructor({
        name,
        courses = [],
        cursosAgregados = [],
        cursosEnProgreso = [],
        cursosAprobados = [],
    }){
        this._name = name;
        this.courses = courses;
        this.cursosAgregados = [];
        this.cursosAprobados = [];
        this.cursosEnProgreso = [];
    }
    get name(){
        return this._name;
    }
    set name(name){
        this._name = name;
    }
}

Getters y setters sin la sintaxis de clases puede ser asi?

const counter = (() => {
  let privateCounter = 0;
  function changeBy(val) {
    const id = crypto.randomUUID();
    return privateCounter +=  id +val;
  }

  return {
    increment: () => changeBy(1),
    decrement: () => changeBy(-1),
    value: () => privateCounter,
  }
});
const idi = counter().value();
const privateId = counter().increment();
const privateId2 = counter().decrement();
const privateId3 = counter().increment();
console.log(idi,privateId);
console.log(privateId3);
console.log(idi,privateId2);
// clase curso
class Course{
    constructor({
        name,
        classes = [],
    }){
        this._name = name;
        this.classes = classes;
    }

    get name(){
        return this._name;
    }

    set name(NuevoNombrecito){
        if(NuevoNombrecito === "Curso malito de programacion"){
            console.error("Web... NO!");
        }else{
            this._name = NuevoNombrecito;
        }
    }
}

//instancia de curso
const cursoProgBasica = new Course(
    {
        name : "Curso gratis de programacion basica"
});

const cursoVGS = new Course(
    {
        name : "Curso Introduccion a VGS"
});

const cursoVGS2 = new Course(
    {
        name : "Curso practico VGS"
});

const cursoDefinitivoHTML = new Course(
    {
        name : "Curso definitivo de HTML y CSS"
});

const cursoPracticoHTML = new Course({
    name : "Curso practico de HTML y CSS",
});
// clase ruta de aprendisaje
class LearningPaths{
    constructor({
        name,
        courses = []
    }){
        this.name = name;
        this.courses = courses;
    }
}

// instancias de  rutas de aprendisaje
const escuelaWeb = new LearningPaths({
    name: "Escuela de desarrollo web",
    courses : [
        cursoProgBasica,
        cursoDefinitivoHTML
    ]
});

const escuelaData = new LearningPaths({
    name: "Escuela de DataScience",
    courses: [
        cursoPracticoHTML,
        cursoDefinitivoHTML,
    ]
});

const escuelaVgs = new LearningPaths({
    name: "Escuela de Vgs",
    courses: [
        cursoVGS,
        cursoVGS2
    ]
});


// clase estudiante
class Student{
    constructor({
        name, 
        username,
        email,
        twitter = undefined,
        instagram = undefined,
        facebook = undefined,
        approvedCourses = [],
        learningPaths = []
    }){
        this.name = name; 
        this.username = username;
        this.email = email;
        this.socailMedia={
            twitter,
            instagram,
            facebook
        };
        this.approedCourses = approvedCourses;
        this.learningPaths = learningPaths;
    }
}   

// instancias de la clase estudiante
const victor = new Student({
    name : "Victor Hugo Cruz",
    username : "hugutiobody",
    email : "[email protected]",
    learningPaths : [
        escuelaWeb,
        escuelaData
    ]
});

const vanesa = new Student({
    name : "Vanesa Pozo",
    username : "vanesita024",
    email : "[email protected]",
    learningPaths : [
        escuelaVgs,
        escuelaData
    ]
});

const emanuel = new Student({
    name : "Emanuel Cruz Pozo",
    username : "emita",
    email : "[email protected]",
    twitter : "emitas_pro"
});

Me gusta esta forma de get y ser mas que la de java

Hola acá dejo dos formas de resolverlo

function pruebaGetSet(name) {
this._name = name;
}
//Forma Uno
pruebaGetSet.prototype.defineGetter(‘name’, function() {return this._name;});
pruebaGetSet.prototype.defineSetter(‘name’, function(val) {this._name = val;});

//Forma Dos
pruebaGetSet.prototype = {
get name() {
return this._name;
},
set name(name){
this._name = name;
}
}

Es importante tener en cuenta el guion bajo que se agrega en el _name. Si ese guion bajo no se agrega, no va a funcionar…

Sintaxis Prototipos

let errorNames = [
    "El Curso es Malo",
    "Curso Malito de Programación",
    "Curso Difícl de Programación",
    "Curso Imposible de Programación",
];

function SintaxisPrototype(value1, value2) {
    this._value1 = value1;
    this.value2 = value2;
}

SintaxisPrototype.prototype = {
    get value1(){
        return this._value1;
    },
    set value1(addNewName){
        if(addNewName === errorNames) {
            console.error("Tranquilizate Maquinola");
        } else {
            this._value1 = addNewName;
        }
    }
    
}

El operador de estricta igualdad === revisa si dos operandos son iguales y produce un resultado Booleano. A diferencia del operador de igualdad regular ==, el operador de estricta igualdad siempre considera que los operandos de distinto tipo de valor son diferentes y nunca similares.

console.log(1 === 1);
// expected output: true

console.log('hello' === 'hello');
// expected output: true

console.log('1' ===  1);
// expected output: false

console.log(0 === false);
// expected output: false

Mi código :3

class Estudiante{
constructor({name,age,correo,facebook,twitter,insta}){
    this._name=name;
    this._age=age;
    this._socialMedia={
        facebook,
        twitter,
        insta
    }
}

get name(){
    return this._name
}
set name(nuenoName){
    this._name=nuenoName;
}

get age(){
    return this._age
}
set age(nuenoAge){
    this._age=nuenoAge;
}
get socialMedia(){
    return this._socialMedia

}
set socialMedia(nueva){
    this._socialMedia=nueva;
}
};




const Pedrito=new Estudiante({name:"Pedro",age:20,facebook:"Pedro MM"})

Por ahora sólo he asignado getters y setters para las clases “LearningPaths” en los atributos name y**_ category _** y para la clase “Clase” en el atributo name.
En ambos casos definí como condicional, por ahora, que no se puedan asignar valores vacíos ni undefined.
El código es este:

Clase Clase

class Clase{
    constructor({
        name,
        instructor,
        level,
    }){
        this._name = name;
        this.instructor = instructor;
        this.level = level;
    }
    get name(){
        return this._name;
    }
    set name(nuevoNombre){  
        if(nuevoNombre === "" || typeof nuevoNombre === "undefined"){
            console.log("El nombre de la clase no es válido o no ha sido asignado.")
        }
        else{
            this._name = nuevoNombre;
        }
    }
};

Clase LearningPaths:

class LearningPath{
    constructor({
        name,
        courses = [],
        coursesNumber,
        category,
        instructors = [],
        projects = [],
        blogPosts = [],
        blogPostsNumber,
    }){
    this._name = name;
    this.courses = courses;
    this.coursesNumber = coursesNumber;
    this._category = category;
    this.instructors = instructors;
    this.projects = projects;
    this.blogPosts = blogPosts;
    this.blogPostsNumber = blogPostsNumber;
    }

    get name(){
        return this._name;
    }
    set name(nuevoNombre){ 
        if(nuevoNombre === "" || typeof nuevoNombre === "undefined"){
            console.error("El nombre de curso no es válido o no ha sido asignado.")
        }
        else{
            this._name = nuevoNombre;
        }
    }
    get category(){
        return this._category;
    }       
    set category(nuevaCategoría){
        if(nuevaCategoría === "" || typeof nuevaCategoría === "undefined"){
            console.error("Categoría no asignada o no válida.")
        }
        else{
            this._category = nuevaCategoría;
        }
    }
}

Buen dia campeon…

class Student {
  constructor({
    name,
    age,
    nationality,
    email,
    twitter = undefined,
    instagram = undefined,
    facebook = undefined,
  }) {
    this._name = name;
    this._age = age;
    this.nationality = nationality;
    this.email = email;
    this._socialMedia = {
      twitter,
      instagram,
      facebook
    };
  }
  get name() {
    return this._name;
  }
  set name(newName) {
    this._name = newName;
  }

  get age() {
    return this._age;
  }
  set age(newAge) {
    this._age = newAge;
  }

  get socialMedia() {
    return this._socialMedia;
  }
  set socialMedia(newsocialMedia) {
    this._socialMedia= newsocialMedia;
  }
};

const user = new Student({
  name:"Katherine", 
  age: 25, 
  nationality: "US",
  twitter: "@katherine_miller",
  instagram: "@katherine_miller",
  email: "[email protected]",
});

.- user.socialMedia.twitter = undefine

Utilice setter and getter para hacer un filtro de nombres baneados

let bannedList = ['Elver Galarga', 'Adolf Hitler']
class Student {
    constructor({
        nombre, edad, twitter=undefined, facebook = undefined, instagram=undefined, cursosAprobados = [], learningPaths=[], email
    }){
    this._nombre = nombre
    this.edad = edad
    this.cursosAprobados = cursosAprobados
    this.learningPaths = learningPaths
    this.email = email
}

get nombre(){
    return this._nombre
}
set nombre(nuevoNombre){
    if (bannedList.includes(nuevoNombre)){
        console.error('wey... no, escoge un nombre apropiado')
    }
    else{
        this._nombre = nuevoNombre
    }

}
}

Tambien podemos usar el operador ternario para la condicion

  set name(nuevoNombre) {
    (nuevoNombre === 'Curso Programacion Basica') 
    ? this._name = nuevoNombre : console.error('No puedes hacer eso');
  }

Aca lo que hice fue condicionar para que no se cambie el nombre, ya que no podemos saber que nombre se inventara el usuario, claro existen mejores formas pero para tema de este curso, funciona bien.

One of the core concepts of OOP is encapsulation. An important part of encapsulation is that data (object properties) should not be directly accessed or modified from outside the object. To access or modify a property we would use a getter (access) or a setter (modify), which are specific methods we define in our class.

Como reto le agregue una clase a los cursos y a esa misma clase le agregue comentarios, luego dentro de los comentarios agregue aportes y preguntas, aquí el código (se aceptan consejos para mejorar, muchas gracias):

<code>
class Coment {
    constructor ({
        text,
        img,
        link
    }) {
        this.text = text
        this.img = img
        this.link = link
    }
}

class Ask extends Coment {

}

const coment1 = new Coment ({
    text: 'Excelente clase!',
    img: 'url: www.imagenesDeCodigo.com',
    link: 'url:...'
})

const ask1 = new Ask ({
    text: 'Tengo una duda en el minuto 2:36',
})

class Class {
    constructor ({
        name,
        duration,
        coments = {
            aports: [],
            asks: []
        }
    }) {
        this.name = name
        this.duration = duration
        this.coments = coments
    }
}

const clasePoo = new Class ({
    name: '¿Qué es la Programación Orientada a Objetos?',
    duration: '3 min',
    coments: {
        aports: [coment1],
        asks: [ask1]
    }
})

class Course {
    constructor({
        name,
        clases = [],
    }) {
        this._name = name
        this.clases = clases
    }

    get name() {
        return this._name
    }

    set name(nuevoNombre) {
        if (nuevoNombre === 'Curso Malo de Programación Básica') {
            console.error('Wey... no')
        } else {
            this._name = nuevoNombre
        }
    }
}

const cursoProgBasica = new Course ({
    name: 'Curso Gratis de Programación Básica',
    clases: [clasePoo]
})

const cursoDefinitivoHtml = new Course ({
    name: 'Curso definitivo de HTML y CSS',
    clases: [clasePoo]
})

const cursoPracticoHtml = new Course ({
    name: 'Curso Práctico de HTML y CSS',
    clases: [clasePoo]
})

class LearningPath {
    constructor({
        name,
        courses = []
    }){
        this.name = name
        this.courses = courses
    }
}

const escuelaWeb = new LearningPath ({
    name: 'Escuela de Desarrollo Web',
    courses: [
        cursoProgBasica,
        cursoDefinitivoHtml,
        cursoPracticoHtml
    ]
})

const escuelaData = new LearningPath ({
    name: 'Escuela de Data Science',
    courses: [
        'Programación Básica',
        'Curso de DataBusiness',
        'Curso de DataViz',
    ]
})

const escuelaVgs = new LearningPath ({
    name: 'Escuela de Videojuegos',
    courses: [
        'Programación Básica',
        'Curso de Unity',
        'Curso de Unreal',
    ]
})

class Student {
    constructor ({
        name,
        email,
        userName,
        twitter = undefined,
        instagram = undefined,
        facebook = undefined,
        approvedCourses = [],
        learningPaths = [],
    }) {
        this.name = name
        this.email = email
        this.userName = userName
        this.socialMedia = {
            twitter,
            instagram,
            facebook,
        }
        this.approvedCourses = approvedCourses
        this.learningPaths = learningPaths
    }
}

const oscar = new Student({
    name: 'Oscar Mtz',
    userName: 'oscarmtz',
    email: '[email protected]',
    twitter: 'oscaramtz',
    approvedCourses: 
    [escuelaWeb.courses[0],
     escuelaWeb.courses[1],
     escuelaWeb.courses[2]
    ],
    learningPaths: [escuelaWeb, escuelaData],
})

const salvador = new Student({
    name: 'Salvador',
    userName: 'Salvador Gzz',
    email: '[email protected]',
    twitter: 'salvador_gzz',
    approvedCourses:
    [escuelaData.courses[0],
     escuelaData.courses[1]
    ],
    learningPaths: [escuelaData, escuelaWeb],
}) 
class pcs{    constructor({        marca,modelo,precio    }){        this.\_marca =marca;        this.\_modelo =modelo;        this.\_precio =precio;    }     get marca (){        return this.\_marca;    }    set marca(a){        if(a != this.\_marca){            console.log("No se puede cambiar de nombre a un valor inmutable")        }             }    get modelo (){        return this.\_modelo;    }    set modelo(a){        let minus = a.toLowerCase();        if(minus == "oled" || minus == "quick" || minus == "faster" ){            this.\_modelo=  minus;            alert("Cambio realizado éxitosamente")                   }        else{            console.log("Modelo no registrado en el sistema")        }    }     get precio (){        return this.\_precio;    }    set precio(a){        let number = Number(a)        if(number < 100){            alert("No se puede asignar un valor tan bajo")                }         else if(number < 10000){            alert("No se puede asignar un valor tan alto")                    }          else{            this.\_precio=  number;            alert("Cambio realizado éxitosamente")           }    }     }
Mi humilde aporte: class pcs{    constructor({        marca,modelo,precio    }){        this.\_marca =marca;        this.\_modelo =modelo;        this.\_precio =precio;    }     get marca (){        return this.\_marca;    }    set marca(a){        if(a != this.\_marca){            console.log("No se puede cambiar de nombre a un valor inmutable")        }             }    get modelo (){        return this.\_modelo;    }    set modelo(a){        let minus = a.toLowerCase();        if(minus == "oled" || minus == "quick" || minus == "faster" ){            this.\_modelo=  minus;            alert("Cambio realizado éxitosamente")                   }        else{            console.log("Modelo no registrado en el sistema")        }    }     get precio (){        return this.\_precio;    }    set precio(a){        let number = Number(a)        if(number < 100){            alert("No se puede asignar un valor tan bajo")                }         else if(number < 10000){            alert("No se puede asignar un valor tan alto")                    }          else{            this.\_precio=  number;            alert("Cambio realizado éxitosamente")           }    }     }
Para este reto: Cómo usamos Getters y Setters cuando usamos prototipos de JS sin la sintaxis de clases. Esta fue mi primer propuesta con un objeto literal: ```js // objeto literal const Riley = { // propiedades _nombre: 'Riley ', segundoNombre: 'Elphaba ', apellido: 'Andersen', _edad: 13, cursosAprobados: [ 'Curso Definitivo de HTML y CSS', 'Curso Práctico de HTML y CSS' ], residencia: 'San Francisco', // Crearemos positvos aprobarCurso(nuevoCurso) { this.cursosAprobados.push(nuevoCurso) }, get nombre() { return this._nombre; }, get edad() { return this._edad; }, set nombre(nuevoNombre) { this._nombre = nuevoNombre; }, set edad(nuevaEdad) { this._edad = nuevaEdad; } }; ```

Si necesito corregir algo, me lo dicen, es bueno mejorar. Les muestro mi ejercicio:

class Course {
    constructor({
        name,
        classes = [],
    }) {
        this._name = name;
        this._classes = classes;
    }

    get name() {
        return this._name;
    }

    set name(nuevoNombre) {
        if (nuevoNombre === "Curso Malito de Programacion Basica") {
            console.error("Web.... no");
        } else {
        this._name = nuevoNombre;
        }
    }
    get classes() {
        return this._classes;
    }
    set classes(noChange) {
        if (noChange ===! classes) {
            console.log("No juegues con fuego, saldrás perdiendo");
        } else {
            this._classes = classes;
        }
    }
};

Get y set son prácticos para el acceso a propiedades de los objetos que resultan de computar otras propiedades que ya existen. Vamos a realizar un ejemplo para penetrar más en los getters y los setters de JavaScript, añadiremos un nuevo uso para que podamos comprenderlos mejor y veremos el funcionamiento de set, para determinar un valor computado.

En este ejemplo, disponemos de un objeto intervalo que, para su implementación, define un valor máximo y uno mínimo, aunque queremos tener algo que nos ofrezca los valores, enteros, comprendidos en ese intervalo.

Así lo resolveríamos de forma tradicional:

var intervalo = {
  valorMinimo: 3,
  valorMaximo: 4,
  valoresContenidos: function() {
    var contenidos = [];
    for(var i=this.valorMinimo; i<=this.valorMaximo; i++) {
      contenidos.push(i);
    }
    return contenidos;
  }
}

Ejecutamos el método siguiente para acceder a los valores contenidos:

var intervalo = {
  valorMinimo: 3,
  valorMaximo: 7,
  get valoresContenidos() {
    var contenidos = [];
    for(var i=this.valorMinimo; i<=this.valorMaximo; i++) {
      contenidos.push(i);
    }
    return contenidos;
  },
}

Hay que tener en cuenta que no podemos recibir ningún parámetro con las propiedades generadas con get, ya que se añaden con funciones.

Llamaríamos al método así:

var valores = intervalo.valoresContenidos;

Por último, para ver la construcción set, recibiremos un parámetro con aquello que se tenga que asignar y efectuar los cambios oportunos en las propiedades de los objetos.

var intervalo = {
  valorMinimo: 3,
  valorMaximo: 7,
  get valoresContenidos() {
    var contenidos = [];
    for(var i=this.valorMinimo; i<=this.valorMaximo; i++) {
      contenidos.push(i);
    }
    return contenidos;
  },
  set valoresContenidos(arrayValores) {
    arrayValores.sort();
    this.valorMinimo = arrayValores[0];
    this.valorMaximo = arrayValores[arrayValores.length - 1];
  }
}

El setter se define de igual forma que el getter. Se usa la función para recibir el dato que tengamos que “setear”, en el se invoca mediante una asignación.

intervalo.valoresContenidos = [5, 6, 2, 9, 3];

El valor que asignamos en la propiedad definida como un setter es el que se recibe como valor del parámetro.

Cuando utilizo prototipos en JavaScript sin la sintaxis de clases, se puede lograr un comportamiento similar a getters y setters con un poco de trabajo manual.// Crear un constructor de Persona function Persona(nombre, edad) { this.\_nombre = nombre; this.\_edad = edad; } // Getter para obtener el nombre Persona.prototype.getNombre = function() { return this.\_nombre; } // Setter para asignar un nuevo nombre Persona.prototype.setNombre = function(nuevoNombre) { this.\_nombre = nuevoNombre; } // Getter para obtener la edad Persona.prototype.getEdad = function() { return this.\_edad; } // Setter para asignar una nueva edad Persona.prototype.setEdad = function(nuevaEdad) { if (nuevaEdad > 0) { this.\_edad = nuevaEdad; } else { console.error('La edad debe ser un número positivo.'); } } // Crear una instancia de Persona var juan = new Persona('Juan', 30); console.log(juan.getNombre()); // Salida: Juan console.log(juan.getEdad()); // Salida: 30 juan.setNombre('Juanito'); console.log(juan.getNombre()); // Salida: Juanito juan.setEdad(-5); // Intento asignar una edad negativa, mostrará un error en la consola. ```js // Crear un constructor de Persona function Persona(nombre, edad) { this._nombre = nombre; this._edad = edad; } // Getter para obtener el nombre Persona.prototype.getNombre = function() { return this._nombre; } // Setter para asignar un nuevo nombre Persona.prototype.setNombre = function(nuevoNombre) { this._nombre = nuevoNombre; } // Getter para obtener la edad Persona.prototype.getEdad = function() { return this._edad; } // Setter para asignar una nueva edad Persona.prototype.setEdad = function(nuevaEdad) { if (nuevaEdad > 0) { this._edad = nuevaEdad; } else { console.error('La edad debe ser un número positivo.'); } } // Crear una instancia de Persona var juan = new Persona('Juan', 30); console.log(juan.getNombre()); // Salida: Juan console.log(juan.getEdad()); // Salida: 30 juan.setNombre('Juanito'); console.log(juan.getNombre()); // Salida: Juanito juan.setEdad(-5); // Intento asignar una edad negativa, mostrará un error en la consola. ``` Este código crea una función constructora llamada `Persona`. Luego, define métodos `getNombre`, `setNombre`, `getEdad`, y `setEdad` en el prototipo de `Persona` que pueden ser utilizados como getters y setters para las propiedades `_nombre` y `_edad`. Por ejemplo, `juan.getNombre()` obtendrá el nombre de `juan`.

Se me ocurrió solicitar una contraseña para poder permitir la modificación del código en vez de restringir un string especifico. No se si esto sea del todo viable, o hay un mejor método.

class Course {
    constructor({
        name,
        classes = [],
    }){
        this._name = name;
        this.classes = classes;
    }

    get name () {
        return this._name;
    }

    set name(nuevoNombre){
        const pass = prompt("Ingresa tu contraseña de autorización")
        if (!(pass === 1234)){
            console.error("No tan rápido ;) ");
        }   else{
            this._name = nuevoNombre;
        }
        
    }
}

const CursoProgBasica = new Course({
    name: "Curso Gratis de Programación Básica",
})
Que interesante que cuando estuve estudiando programación no entendía mucho de estos conceptos, me parecían muy complicados. Ahora varios años después de estar trabajando como desarrollador y tomar este curso, me parece todo menos complejo y más fácil de entender.

Esta es la primera solución que iba construyendo

function Course({ name, classes }) {
  this._name = name;
  this.classes = classes;

  this.name = () => {
    return this._name;
  };

  this.name = ({ name }) => {
    if (name <= 3) {
      console.log("It's too short");
      return;
    }

    this._name = name;
  };
}

const angular = new Course({
  name: "Fundamentos de angular",
  classes: 12,
});

Esta es la segund solución con inteligencia artificial(Chat AI) en este caso jejeje

function Course({ name, classes = [] }) {
  this._name = name;
  this.classes = classes;
}

Course.prototype = {
  get name() {
    return this._name;
  },

  set name(newName) {
    if (newName.length <= 3) {
      console.error("It's too short");
    } else {
      this._name = newName;
    }
  },
};

const angular = new Course({ name: "Angular", classes: 19 });

Lo que entendí es que los getters and setters son metodos nos permiten acceder a las propiedades de los objetos.

Les comparto como hice, para que cuando alguien quiera modificar el nombre al curso le aparezca error

set name(nuevoNombrecito){
        if(nuevoNombrecito !== this.name){
            console.error("no puedes cambiar el nombre de el curso")
        }
        else{
            this._name = nuevoNombrecito;
        }
    }

La verdad me quedaron algunas dudas sobre los getters y setters pero con la documentación oficial pude entenderlo mejor, aqui les dejo los enlaces:

no se pero siento una gran aburrimiento con este curso…

Buena clase profe, pero no entendí muy bien qué tienen que ver los setters y getters con el encapsulamiento. 😥

El cumpa se hace muchas bolas, acá lo explican mejor: https://www.youtube.com/watch?v=iPw-5EOqh5Y

Getters y Setters

Son métodos de acceso que nos permiten traer los valores de cada uno de los atributos que tengamos de una clase y poder, establecer o modificarlos.

get: permite obtener los datos de una propiedad de la clase, para hacer una operación o mostrar en pantalla.

set: permite establecer o modificar datos si estos están cargados.

Tuve problemas al utilizar módulos para separar las clases en diferentes archivos. Luego de investigar un buen tiempo, encontré la solución de window.

const FreddyVega = new Teacher({
  id: 1,
  name: 'Freddy Vega',
  speciality: 'CEO',
});
console.log(FreddyVega);

window.FreddyVega = FreddyVega;

Luego de crear la instancia la mandamos a window, de manera que en la consola ya podemos acceder a las propiedades con window así (por ejemplo):

window.FreddyVega.speciality;

Dejo enlace que describe el cambio de convención (_) a uno usado directamente por Javascript para el manejo de atributos privados (#). 💛🤟🏻

🔗 atributos-privados-clases-js

function Student({name, points = 0}){
    this._name = name;
    this._points = points;
}

Student.prototype = {
    constructor : Student,
    get name(){
        return this._name;
    },
    set name(newName){
        this._name = newName;
    }
}

Hay muchos compañeros que dicen usar la sintaxis del # para declarar las variables privadas, pero al acceder a un propiedad como normalmente lo haría me sigue devolviendo el valor, así que tan segura no es 🤔
.
.
Mi código:

	class Course{
    #name;
    #classes;

    constructor({name, classes = []}){
        this.#name = name;
        this.#classes = classes; 
    }

    get name(){
        return this.#name;
    }

    set name(newName){
        this.#name = newName;
    }

}

const cursoPrgmBasica = new Course({name: "Curso de programacion Basica"});

Les comparto un enlace para expandir el conocimiento de los Getters y Setters 😉

Como serian los setters y getters para los arrays y objetos?

¿Las clases van del lado del back end o front end?

Buenas, tengo un temita con el get set. Contexto: Se crea una clase con un atributo privado y un metodo que lee la propiedad y la modifica si la condicion evaluada es correcta (eg: leer un array de cursos de una ruta, o modificar dicho array). La consulta seria si, al momento de evaluar/modificar el atributo privado desde el metodo de la misma clase, corresponde evaluar el atributo privado (\_var) o deberia seguirse la convencion del get y set aqui tambien. ![](https://static.platzi.com/media/user_upload/image-ad348ea1-dbb1-426a-a35e-201690befb6d.jpg)