RORO PIRRORO
Introducción
¿Qué hay dentro de los objetos en JavaScript?
Profundicemos en los objetos
Static: atributos y métodos estáticos en JavaScript
Métodos estáticos del prototipo Object
Object.defineProperty
Cómo copiar objetos en JavaScript
Cómo funciona la memoria en JavaScript
Shallow copy en JavaScript
Qué es JSON.parse y JSON.stringify
Recursividad en JavaScript
Qué es recursividad
Deep copy con recursividad
Playgrounds: Hacer freeze de un objeto de forma recursiva
Abstracción y encapsulamiento sin prototipos
Factory pattern y RORO
Abstracción con objetos literales y deep copy
Module pattern y namespaces: propiedades privadas en JavaScript
Getters y setters
Cómo identificar objetos
Qué es duck typing
Duck typing en JavaScript
Instance Of en JavaScript con instancias y prototipos
Atributos y métodos privados en prototipos
Creando métodos estáticos en JavaScript
Próximos pasos
¿Quieres más cursos de POO en JavaScript?
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Juan David Castro Gallego
Factory pattern (o fábrica de objeto) y RORO (Recibir un Objeto, Retornar un Objeto) son dos patrones que nos ayudan a crear moldes de objetos a partir de funciones. Con ello ya no sería necesario utilizar objetos literales ni deep copy con recursividad.
Generaremos una función que nos permita generar nuevos estudiantes. Esta función va a recibir un objeto (con los datos del nuevo estudiante) como parámetro y devolverá el nuevo objeto generado.
function isObject(subject) {
return typeof subject == "object";
}
function isArray(subject) {
return Array.isArray(subject);
}
function createStudent({
name,
email,
age,
twitter,
instagram,
facebook,
approvedCourses,
learningPaths,
}) {
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
Antes de crear nuevos objetos, podríamos darles unas mejoras a nuestra función:
approvedCourses
y learningPaths
deberían ser arreglos vacíos por defecto y así evitamos que sean undefined
en caso de que no se envíen datos en el momento que se genere un nuevo estudiante: function isObject(subject) {
return typeof subject == "object";
}
function isArray(subject) {
return Array.isArray(subject);
}
function createStudent({
name,
email,
age,
twitter,
instagram,
facebook,
approvedCourses = [], // 👈👈
learningPaths = [], // 👈👈
}) {
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
createStudent
no mandamos siquiera un objeto vacío como argumento, nos dará un error. Evitemos esto declarando que el parámetro que recibe la función puede ser un objeto vacío por defecto: function isObject(subject) {
return typeof subject == "object";
}
function isArray(subject) {
return Array.isArray(subject);
}
function createStudent({
name,
email,
age,
twitter,
instagram,
facebook,
approvedCourses = [],
learningPaths = [],
} = {}) { // 👈👈
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
email
sean obligatorios de enviar, pues, no todos los atributos se deberían quedar como undefined
ni tampoco deberíamos poner valores por defecto a ciertos datos personales de un estudiante. Por tanto, deberíamos avisar mediante un mensaje de error personalizado que ciertos campos son obligatorios: function isObject(subject) {
return typeof subject == "object";
}
function isArray(subject) {
return Array.isArray(subject);
}
// Creamos una función con el objetivo de generar un Error el cual
// tendrá un mensaje customizado por nosotros.
// Como parámetro indicamos el nombre del atributo que no se está enviando (String)
function requiredParam(param) { // 👈👈
throw new Error(param + " es obligatorio"); // Este es el mensaje de error generado
}
function createStudent({
// Por defecto, invocamos a la nueva función requiredParam en aquellos
// atributos que deseamos que sean obligatorios. Indicamos como argumento el nombre
// de dicho atributo.
name = requiredParam("name"), // 👈👈
email = requiredParam("email"), // 👈👈
age,
twitter,
instagram,
facebook,
approvedCourses = [],
learningPaths = [],
} = {}) {
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
Ahora, si intentamos crear un objeto que no tenga, por ejemplo, asignado un valor en la propiedad `name`, la consola nos mostrará el mensaje de error que creamos:
const juan = createStudent({ email: "[email protected]"});
![La consola nos muestra un mensaje con formato de Error diciendo que el atributo name es obligatorio](https://static.platzi.com/media/articlases/Images/atributo-obligatorio-en-un-mensaje-de-error-de-la-consola-curso-intermedio-de-programacion-orientada-a-objetos-en-javascript.jpg)
Aprendamos ahora a cómo crear [propiedades privadas en JavaScript](https://platzi.com/clases/2419-javascript-poo-intermedio/39817-module-pattern-y-namespaces-propiedades-privadas-e/). 👨💻🚀
*Contribución creada por: Martín Álvarez (Platzi Contributor)*
Aportes 32
Preguntas 8
RORO PIRRORO
Comparto el código usando TS 💙
En Typescript podemos declarar interfaces (es algo así como un contrato para crear un objeto), y declarar propiedades que sean opcionales con el signo de interrogación ‘?’, las demás serán obligatorias, en caso de no cumplir con el contrato, el lenguaje te avisara antes de ejecutar el código. 😀
.
Elegant patterns in modern JavaScript: RORO
/* Codigo Deep Copy */
// Requerimientos de parametros obligatorios
function requiredParam(param){
throw new Error(param + " Campo obligatorio");
}
// Fabrica de estudiantes
function createStudent({
name = requiredParam("name"),
email = requiredParam("email"),
age,
twitter,
instagram,
facebook,
approvedCourses = [],
learningPaths = [],
} = {}) {
return {
name,
age,
email,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
const carlos = createStudent({
name: 'Carlito',
age: 20,
email: '[email protected]',
twitter: 'carlitosmzz',
}); // {}
Este curso, de lejos, se queda como de los mejores, Juan es todo un crack, tanto enseñando como sabiendo que enseñar 😮
Recibir un objeto, retornar un objeto, anotado
**RORO **= Recibir un Objecto, y Retornamos otro Objecto.
Dentro de una función, recibimos un solo parámetro que es un objecto, el cual internamente contiene varias propiedades, con las cuales retornara otro nuevo objeto.
Me faltó el “Facebook es undefined porque ¡¿Quién tiene facebook?!” del profee
RORO es un patrón de diseño que consiste en crear una función que devuelve un objeto.
RO -> Recibir un objeto
RO -> Retornar un objeto
function requiredParam(param){
throw new Error(param + "missing parameter")
}
el código anterior es una función que retorna un error.
function createStudent({
name = requiredParam("name")
email = requiredParam("email"),
age,
aprrovedCourses = [],
learningPaths = [],
socialMedia,
} = {})
tira error cuando no estamos eenviando ninguna propiedad name o email.
Puedes también crear una fabrica de instancias de prototipos con esta función ejemplo:
function createNewCourse({name,school,score,lang,freeAcces}){
return new Courses({
name,
school,
score,
lang,
freeAcces
})
}
Es un patrón de código en el que se envía como parámetro a una función un objeto para devolver otro objeto, y el beneficio de esto principalmente es:
Like si te gustan los frijoles tanto como a juan!! 😂😆
Espectacular revisar lo de RORO añadiendo los parámetros por defecto.
se pueden escuchar carros de formula 1 en el minuto 10:38
function requiredParam(param) {
throw new Error(`Missing required parameter: ${param}`);
}
function createStudent({
name = requiredParam('name'), //Mostará error si está vacío
email = requiredParam('email'),
age,
twitter,
facebook,
instagram,
approvedCourses = [], //valor por defecto
learningPaths = [], //valor por defecto
} = {} /*Por defecto es un objeto vacío*/ ) {
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
facebook,
instagram
},
};
}
const juan = createStudent({
name: 'Juan',
email: '[email protected]',
age: 20,
twitter: '@fjuandc',
})
RORO = Recibir un Objecto, y Retornar otro Objecto.
Nos ayudan a crear moldes de objeto, pero no a partir de objetos literales, sino con funciones:
function requiredParams(param) {
throw new Error(param + ": es un parámetro requerido")
};
function createStudent({
name = requiredParams("name"),
age = requiredParams("age"),
email,
twitter,
instagram,
github,
approvedCourses = [],
learningPaths =[],
} = {}) {
return {
name,
email,
age,
socialMedia: {
twitter,
instagram,
github
},
approvedCourses,
learningPaths,
}
};
const felipe = createStudent({
name: "Felipe",
email: "[email protected]",
age: 28,
github: 'afelipelds',
});
Lo que está haciendo el profe en la función createStudent, se llama destructuring, que en términos generales lo que hace es una especie de desempaquetado de las propiedades de objetos o arrays:
entonces en vez de él hacer esto:
function createStudent(estudent) {
return {
name: student.name,
age: student.age
...
}
}
lo que hace es un destructuring ese objeto student:
function createStudent({name, age, ... }) {
return {
name,
age
...
}
}
Un enlace si quieren profundizar más:
Creemos una función que creará objetos:
-Recibe como parametro un objeto para que no importe el orden en que se envían las propiedades
-Igualamos el parametro a un objeto vacío para que no exista error en caso de que no enviemos argumentos al llamar la función.
function createStudent({
name,
email,
age,
twitter,
instagram,
facebook,
approvedCourses = [],
learningPaths = [],
} = {})
-Retornamos un objeto con todas las propiedades enviadas (las propiedades no enviadas seran undefined)
{
return {
name,
email,
age,
approvedCourses,
learningPaths,
socialMedia: {
twitter,
instagram,
facebook,
},
};
}
-Pero si vamos a necesitar propiedades obligatorias, por esto, cuando no se envien vamos a lanzar un error
function requiredParam(param) {
throw new Error(param + " es obligatorio");
}
function createStudent({
name = requiredParam("name"),
email = requiredParam("email"),
}={})
De verdad este curso es uno de los mejores de Platzi.
Increible Juan!
En esta clase a comparación de la anterior aprendimos a crear objetos haciendo uso de Factory Pattern y el patrón Roro
Me gustan mas las explicaciones del profesor Nicolas, mucho mas claro al usar objetos mas “reales”, es decir
Edificio{
apartamento101{
tipoApto{
apto: suite
},
familiaRamirez{
ana{
genero: femenino,
nombreCompleto: Ana Ramirez,
edad: 30
},
sergio{
genero: masculino,
nombreCompleto: Sergio Ramirez,
edad: 32
},
}
},
apartamento201{
...
}
en vez de
{a:b, {juanito: juan no esjuan}
La función requiredParam
es una función auxiliar que se utiliza para asegurarse de que ciertos parámetros sean proporcionados al llamar a otra función. Su propósito es lanzar un error si un parámetro requerido no se pasa o se pasa como undefined
.
.
En el código que proporcionaste, la función requiredParam
se utiliza en la función createStudent
para los parámetros name
y email
. Estos parámetros se definen utilizando la sintaxis de desestructuración de objetos y se les asigna el valor de requiredParam("name")
y requiredParam("email")
respectivamente.
.
Cuando se llama a la función createStudent
, los valores de name
y email
deben ser proporcionados como argumentos. Si alguno de estos argumentos no se pasa o se pasa como undefined
, la función requiredParam
lanzará un error. El mensaje de error especificado en la función requiredParam
indica qué parámetro es obligatorio.
.
Por ejemplo, si se llama a la función createStudent
de la siguiente manera:
createStudent({ name: "John Doe" });
Se lanzará un error con el mensaje “email es obligatorio”, porque el parámetro email
no se proporcionó.
.
En resumen, la función requiredParam
es una forma de asegurarse de que se proporcionen todos los parámetros requeridos al llamar a una función y de lanzar un error si alguno de ellos falta. Esto ayuda a garantizar que la función se llame con los argumentos adecuados y evita errores o resultados inesperados en el código.
Como que ya no sera necesario utilizar deepCopy() 😕😞
Una forma más sencilla de crear errores, o cualquier otro tipo de respuesta dependiendo del caso de uso, si queremos que una variable sea obligatoriamente tomada en cuenta, es utilizar el operador de fusión nulo o nullish coalescing:
.
Este operador funciona como un OR, con la diferencia de que devolverá el segundo valor únicamente si el primero es un null o un undefined. Se utiliza ??
para representarlo:
const foo = null ?? 'default string';
console.log(foo);
// expected output: "default string"
const baz = 0 ?? 42;
console.log(baz);
// expected output: 0
Pueden leer más al respecto en esta documentación en inglés o en esta documentación en español, en la parte de Operadores lógicos
.
En ese orden de ideas, para generar un error utilizando el código de la clase, basta con colocar esta operación dentro de la función createStudent()
en las propiedades que queramos hacer obligatorias de llenar. Yo lo hice con con name
e email
para que sean obligatorios, pero también lo usé en approvedCourses
y learningPaths
para que muestre una respuesta más amigable que un arreglo vacío o un undefined , quedando de la siguiente manera:
function createStudent({
name,
age,
email,
twitter,
facebook,
instagram,
approvedCourses,
learningPaths
}) {
return {
name: name ?? console.error('Necesitas proporcionar tu nombre'),
age,
email: email ?? console.error('Necesitas proporcionar un email'),
approvedCourses: approvedCourses ?? 'No tienes cursos aprovados',
learningPaths: learningPaths ?? 'No haz elegido rutas de aprendizaje',
socialMedia: {
twitter,
instagram,
facebook,
}
};
}
A continuación, te explicaré brevemente el Factory Pattern (patrón de fábrica) y el concepto de RORO (Receive One, Return One) en JavaScript, y te proporcionaré un ejemplo práctico para cada uno de ellos.
.
// Definición de la clase Employee
class Employee {
constructor(name, role) {
this.name = name;
this.role = role;
}
sayRole() {
console.log(`Soy un ${this.role}`);
}
}
// Definición de la clase Factory
class EmployeeFactory {
createEmployee(name, role) {
return new Employee(name, role);
}
}
// Uso del Factory para crear objetos de empleado
const factory = new EmployeeFactory();
const developer = factory.createEmployee("John Doe", "Desarrollador");
const designer = factory.createEmployee("Jane Smith", "Diseñador");
developer.sayRole(); // Output: Soy un Desarrollador
designer.sayRole(); // Output: Soy un Diseñador
En este ejemplo, el Factory (EmployeeFactory) se encarga de crear objetos de la clase Employee según los parámetros proporcionados. Esto permite crear diferentes tipos de empleados sin que el código que utiliza los objetos tenga que preocuparse por la lógica de creación.
.
.
Ejemplo práctico:
Supongamos que tienes una función que toma un número como argumento y devuelve su cuadrado. Puedes aplicar el concepto RORO de la siguiente manera:
function square(number) {
return number * number;
}
const result = square(5);
console.log(result); // Output: 25
.
En este ejemplo, la función square recibe un argumento (number) y devuelve el resultado del número al cuadrado. Al aplicar el concepto RORO, queda claro que la función toma un solo valor y devuelve otro valor, lo que facilita su comprensión.
Espero que estos ejemplos prácticos te ayuden a entender el Factory Pattern y el concepto RORO en JavaScript. Si tienes alguna otra pregunta, no dudes en hacerla.
Para crear una fábrica de objetos se siguen estos pasos:
Se crea una función la cual debe recibir por parámetro un objeto desestructurado (La ventaja de esto es que, al ejecutar la función, el argumento debe ser un objeto. De tal manera no se debe recordar el orden de los parámetros para poder enviar los argumentos.) y a su vez dicho parámetro debe ser por defecto un objeto vacío. Esto último impide que se generen errores al momento de hacer la ejecución de la función sin ningún argumento porque no se puede desestructurar las propiedades del argumento que, en este caso, tendría valor “undefined”.
La función debe retornar el parámetro, es decir, el objeto desestructurado.
Exterior a la función, se asigna a una variable la ejecución de la función con el argumento (un objeto) que se quiere enviar. En este punto el objeto se crea.
Adicionalmente se puede restringir que algunas propiedades del objeto, que es parámetro en la función, puedan aceptar valores indefinidos asignando a dichas propiedades valores por defecto (como si un parámetro por defecto se tratase) una función externa que cree un error y detenga la ejecución del código utilizando la instrucción throw
.
Wow…! requiredParam
Esto me recuerda mucho a React 🤔🔥
Recibe Objeto
Retorna Objeto
Apuntes de la clase
Factory pattern y RORO
https://mriatorres.notion.site/Factory-pattern-y-RORO-c86bf483cb6541289df96f1a40a033c4
Mi resumen:
/*-----------------Creación de objetos usando funciones-------------------*/
function createStudent({
name,
age
} = {}) { //define que si no se envía nada por argumento, entonces se creará un objeto vació, evitando que salga un error
return {
name,
age
}
}
const rica = createStudent();
console.log(rica); //{ name: undefined, age: undefined }
//Si es que se desea si o si pasar un dato obligatorio, se puede crear un función que retorne error
function requiredParam(param) { // 👈👈
throw new Error(param + " es obligatorio"); // throw new Error es la forma de disparar errores en JS
}
//Entonces esta función se puede pasar por valor de una propiedad
function createStudent2({
name,
age = requiredParam("age")
} = {}) { //en este caso ya no serviría porque se tiene que mandar un valor obligatorio
return {
name,
age
}
}
const terry = createStudent2(); //Error: age es obligatorio
const luis = createStudent2({age:12});
console.log(luis); //{ name: undefined, age: 12 }
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?