Si quieren intentar el reto de objetos sin ver las soluciones, hice el archivo del challenge con instrucciones para que puedan resolverlos.
Código aquí:
NOTA: Copia todo el contenido y reemplázalo en el archivo principal.
Los objetos en JavaScript son la base para construir aplicaciones web confiables. Aquí verás cómo definir pares clave-valor, acceder a propiedades con precisión, evitar errores como TypeError y aplicar optional chaining para que tu lógica no se rompa cuando falte información. Todo con ejemplos claros y buenas prácticas.
¿Qué es un objeto en JavaScript y cómo se define?
Un objeto es una colección de pares clave-valor que agrupa características de algo: nombre, edad, correo, etc. A diferencia de los arreglos que usan índices, los objetos usan claves legibles. Se definen con llaves {} y permiten desde valores primitivos hasta arreglos y otros objetos anidados.
Date.now().Ejemplo base del objeto nota:
// src/quince-objects.js const nota = { ID: 1, title: "Mi primera nota", content: "Contenido de la nota.", createAt: Date.now() };
También puede crecer con más propiedades: edad numérica, isAdmin booleana, o un arreglo dates con valores. Identifícalas bien para no confundir lo que es de un objeto y lo que pertenece a un arreglo.
¿Cómo diferenciar objetos de arreglos?
{} y acceso por clave.[] y acceso por índice.¿Cómo acceder a propiedades con punto y con corchetes?
Existen dos formas. La notación de punto es directa y legible. La notación de corchetes permite usar claves dinámicas desde variables.
console.log(nota.ID); // Acceso por punto. console.log(nota.title); // Acceso por punto. const campo = "content"; // Clave dinámica. console.log(nota[campo]); // Acceso por corchetes.
Atención a los typos en las claves: si escribes tile en lugar de title, no obtendrás el valor esperado. En cadenas de texto el efecto es menor; en nombres de propiedades puede romper la lógica porque la clave cambia.
¿Qué ocurre si la propiedad no existe?
console.log(nota.autor); // undefined. console.log(nota.autor.name); // TypeError: no puede leer 'name' de undefined.
Cuando veas el trace del error, léelo: indica qué propiedad falló y en qué nivel. Entender el mensaje acelera la corrección.
¿Cómo prevenir fallos con optional chaining en datos de una API?
Al consumir datos desde un servidor por medio de una API, la estructura puede cambiar: quizá esperas autor y name, pero no llegan. Sin protección, eso detiene el flujo de la aplicación. Con optional chaining evitas el colapso si algo falta.
// Sin protección: puede lanzar TypeError si 'autor' falta. // console.log(nota.autor.name); // Con optional chaining: seguro ante datos ausentes. console.log(nota?.autor?.name); // undefined si 'autor' o 'name' no existen.
Buenas prácticas:
console.log solo lo necesario para depurar sin ruido.¿Tienes un caso real con objetos, acceso dinámico o optional chaining? Cuéntalo en los comentarios y comparte tu solución.
Los objetos en JavaScript son la base para construir aplicaciones web confiables. Aquí verás cómo definir pares clave-valor, acceder a propiedades con precisión, evitar errores como TypeError y aplicar optional chaining para que tu lógica no se rompa cuando falte información. Todo con ejemplos claros y buenas prácticas.
Un objeto es una colección de pares clave-valor que agrupa características de algo: nombre, edad, correo, etc. A diferencia de los arreglos que usan índices, los objetos usan claves legibles. Se definen con llaves {} y permiten desde valores primitivos hasta arreglos y otros objetos anidados.
Date.now().Ejemplo base del objeto nota:
// src/quince-objects.js
const nota = {
ID: 1,
title: "Mi primera nota",
content: "Contenido de la nota.",
createAt: Date.now()
};
También puede crecer con más propiedades: edad numérica, isAdmin booleana, o un arreglo dates con valores. Identifícalas bien para no confundir lo que es de un objeto y lo que pertenece a un arreglo.
{} y acceso por clave.[] y acceso por índice.Existen dos formas. La notación de punto es directa y legible. La notación de corchetes permite usar claves dinámicas desde variables.
console.log(nota.ID); // Acceso por punto.
console.log(nota.title); // Acceso por punto.
const campo = "content"; // Clave dinámica.
console.log(nota[campo]); // Acceso por corchetes.
Atención a los typos en las claves: si escribes tile en lugar de title, no obtendrás el valor esperado. En cadenas de texto el efecto es menor; en nombres de propiedades puede romper la lógica porque la clave cambia.
console.log(nota.autor); // undefined.
console.log(nota.autor.name); // TypeError: no puede leer 'name' de undefined.
Cuando veas el trace del error, léelo: indica qué propiedad falló y en qué nivel. Entender el mensaje acelera la corrección.
Al consumir datos desde un servidor por medio de una API, la estructura puede cambiar: quizá esperas autor y name, pero no llegan. Sin protección, eso detiene el flujo de la aplicación. Con optional chaining evitas el colapso si algo falta.
// Sin protección: puede lanzar TypeError si 'autor' falta.
// console.log(nota.autor.name);
// Con optional chaining: seguro ante datos ausentes.
console.log(nota?.autor?.name); // undefined si 'autor' o 'name' no existen.
Buenas prácticas:
console.log solo lo necesario para depurar sin ruido.¿Tienes un caso real con objetos, acceso dinámico o optional chaining? Cuéntalo en los comentarios y comparte tu solución.
Si quieren intentar el reto de objetos sin ver las soluciones, hice el archivo del challenge con instrucciones para que puedan resolverlos.
Código aquí:
NOTA: Copia todo el contenido y reemplázalo en el archivo principal.
Adoro los mini tips que da en cada lección. Lo de poner el "?" para evitar el error estoy seguro me va a salvar de muchos dolores de cabeza en el futuro. ¡Gracias!
Done!
function crearUsuario() {
const persona = {
nombre: "Ana",
edad: 28,
email: "ana@example.com",
};
return persona;
}
// --- Reto 2: Obtener nombre ---
// Recibe un objeto usuario.
// Retorna el valor de la propiedad "nombre".
function obtenerNombre(usuario) {
return usuario.nombre;
}
// --- Reto 3: Propiedad dinámica ---
// Recibe un objeto y el nombre de una propiedad (como string).
// Retorna el valor de esa propiedad usando notación de corchetes.
function obtenerPropiedadDinamica(objeto, propiedad) {
const campo = propiedad;
return objeto[campo];
}
// --- Reto 4: Verificar email ---
// Recibe un objeto usuario.
// Retorna true si el usuario tiene la propiedad "email", false si no.
// Pista: usa hasOwnProperty
function tieneEmail(usuario) {
if (usuario.email) {
return true;
} else {
return false;
}
}
// --- Reto 5: Obtener ciudad ---
// Recibe un objeto usuario que puede o no tener dirección.
// Retorna la ciudad del usuario si existe: usuario.direccion.ciudad
// Si no existe alguna parte del camino, retorna undefined (sin errores).
// Pista: optional chaining ?.
function obtenerCiudad(usuario) {
return usuario.direccion?.ciudad;
}
// --- Reto 6: Crear producto ---
// Crea una función sin parámetros.
// Debe retornar un objeto con estas propiedades:
// id: 1
// nombre: "Laptop"
// precio: 999.99
// especificaciones: objeto con marca, memoria y almacenamiento
// marca: "TechBrand"
// memoria: "16GB"
// almacenamiento: "512GB SSD"
function crearProducto() {
const producto = {
id: 1,
nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
memoria: "16GB",
almacenamiento: "512GB SSD",
},
};
return producto;
}
// --- Reto 7: Obtener memoria ---
// Recibe un objeto producto con especificaciones anidadas.
// Retorna el valor de producto.especificaciones.memoria
// Si no existe alguna parte del camino, retorna undefined (sin errores).
function obtenerMemoria(producto) {
return producto.especificaciones?.memoria;
}
// --- Reto 8: Agregar propiedad ---
// Recibe un objeto, el nombre de una propiedad (string) y un valor.
// Agrega esa propiedad con ese valor al objeto.
// Retorna el objeto modificado.
function agregarPropiedad(objeto, nombrePropiedad, valor) {
objeto[nombrePropiedad] = valor;
return objeto;
}
// --- Reto 9: Calculadora con estado ---
// Crea una función sin parámetros.
// Retorna un objeto con tres métodos:
// sumar(numero) → suma el número al valor interno
// restar(numero) → resta el número al valor interno
// obtenerValor() → retorna el valor actual
// El valor empieza en 0.
// Pista: usa "this" para acceder al valor dentro del objeto
function crearCalculadora() {
return {
valor: 0,
sumar(numero) {
this.valor += numero;
return this.valor;
},
restar(numero) {
this.valor -= numero;
return this.valor;
},
obtenerValor() {
return this.valor;
},
};
}
// --- Reto 10: Obtener Twitter ---
// Recibe un objeto usuario con estructura profundamente anidada.
// Retorna usuario.perfil.redes.twitter
// Si no existe alguna parte del camino, retorna "no-disponible"
function obtenerTwitter(usuario) {
return usuario?.perfil?.redes?.twitter || "no-disponible";
}

Dejo mi reto (hice los ejercicios sin solución que comparte Marco Antonio):
// ============================================
// Reto 17: Objetos en JavaScript
// ============================================
// Completa cada función según las instrucciones.
// Ejecuta los tests con:
// npx vitest src/17-objetos-javascript
// ============================================
// --- Reto 1: Crear Usuario
// Crea y retorna un objeto con las siguientes propiedades:
// nombre: "Ana", edad: 28, email: "ana@example.com"
function crearUsuario() {
const usuario = {
nombre: 'Ana',
edad: 28,
email: 'ana@example.com'
}
return usuario;
}
// --- Reto 2: Obtener Nombre
// Recibe un usuario (objeto)
// Retorna la propiedad "nombre" del objeto usuario.
function obtenerNombre(usuario) {
return usuario.nombre;
}
// --- Reto 3: Obtener Propiedad Dinámica
// Recibe: objeto y propiedad
// Retorna el valor de la propiedad indicada.
// Pista: usa acceso con corchetes []
function obtenerPropiedadDinamica(objeto, propiedad) {
return objeto[propiedad];
}
// --- Reto 4: Tiene Email
// Recibe un usuario (objeto)
// Retorna true si el objeto tiene la propiedad "email"
// Retorna false si no existe.
// Pista: usa hasOwnProperty()
function tieneEmail(usuario) {
return usuario.hasOwnProperty('email');
}
// --- Reto 5: Obtener Ciudad
// Recibe un usuario (objeto)
// Retorna la ciudad dentro de: usuario.direccion.ciudad
// Si la propiedad no existe debe retornar undefined.
// Pista: optional chaining
function obtenerCiudad(usuario) {
return usuario.direccion?.ciudad;
}
// --- Reto 6: Crear Producto
// Retorna un objeto con la siguiente estructura:
// id: 1
// nombre: "Laptop"
// precio: 999.99
// especificaciones: {
// marca: "TechBrand",
// memoria: "16GB",
// almacenamiento: "512GB SSD"
// }
function crearProducto() {
const producto = {
id: 1,
nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
memoria: "16GB",
almacenamiento: "512GB SSD"
}
}
return producto;
}
// --- Reto 7: Obtener Memoria
// Recibe el objeto producto
// Retorna la propiedad:
// producto.especificaciones.memoria
// Debe retornar undefined si memoria no existe.
function obtenerMemoria(producto) {
return producto.especificaciones?.memoria;
}
// --- Reto 8: Agregar Propiedad
// Recibe: objeto, nombrePropiedad y valor
// Agrega la propiedad al objeto y asígnale el valor.
// Retorna el objeto actualizado.
function agregarPropiedad(objeto, nombrePropiedad, valor) {
objeto[nombrePropiedad] = valor;
return objeto;
}
// --- Reto 9: Crear Calculadora
// Retorna un objeto con:
// valor: 0
//
// Métodos:
// sumar(num) => suma num al valor
// restar(num) => resta num al valor
// obtenerValor() => retorna el valor actual
//
// Pista:
// usa this.valor dentro de los métodos.
function crearCalculadora() {
const calculadora = {
valor: 0,
sumar(num){
return this.valor += num;
},
restar(num){
return this.valor -= num;
},
obtenerValor(){
return this.valor;
}
}
return calculadora;
}
// --- Reto 10: Obtener Twitter
// Recibe un usuario (objeto)
// Retorna la propiedad: usuario.perfil.redes.twitter
// Si no existe debe retornar:
// "no-disponible"
//
// Pista:
// optional chaining + operador OR
function obtenerTwitter(usuario) {
return usuario?.perfil?.redes?.twitter || "no-disponible";
}
module.exports = {
crearUsuario,
obtenerNombre,
obtenerPropiedadDinamica,
tieneEmail,
obtenerCiudad,
crearProducto,
obtenerMemoria,
agregarPropiedad,
crearCalculadora,
obtenerTwitter,
};
Mi solución al reto:
// ============================================
// Reto 17: Objetos en JavaScript
// ============================================
// Completa cada función según las instrucciones.
// Ejecuta los tests con:
// npx vitest src/17-objetos-javascript
// ============================================
// --- Reto 1: Crear Usuario
// Crea y retorna un objeto con las siguientes propiedades:
// nombre: "Ana", edad: 28, email: "ana@example.com"
function crearUsuario() {
// tu codigo aquí
const objeto1 = {nombre: "Ana", edad: 28, email: "ana@example.com"};
return objeto1;
}
console.log(crearUsuario());
// --- Reto 2: Obtener Nombre
// Recibe un usuario (objeto)
// Retorna la propiedad "nombre" del objeto usuario.
function obtenerNombre(usuario) {
// tu codigo aqui
return usuario.nombre
}
console.log(obtenerNombre({nombre: "Ana", edad: 28, email: "ana@example.com"}));
// --- Reto 3: Obtener Propiedad Dinámica
// Recibe: objeto y propiedad
// Retorna el valor de la propiedad indicada.
// Pista: usa acceso con corchetes []
function obtenerPropiedadDinamica(objeto, propiedad) {
// tu codigo aqui
return objeto[propiedad];
}
console.log(obtenerPropiedadDinamica({nombre: "Ana", edad: 28, email: "ana@example.com"}, 'edad'));
// --- Reto 4: Tiene Email
// Recibe un usuario (objeto)
// Retorna true si el objeto tiene la propiedad "email"
// Retorna false si no existe.
// Pista: usa hasOwnProperty()
function tieneEmail(usuario) {
// tu codigo aqui
if (usuario.hasOwnProperty('email')) {
return true
} else {
return false
}
}
console.log(tieneEmail({nombre: "Ana", edad: 28, email: "ana@example.com"}));
// --- Reto 5: Obtener Ciudad
// Recibe un usuario (objeto)
// Retorna la ciudad dentro de: usuario.direccion.ciudad
// Si la propiedad no existe debe retornar undefined.
// Pista: optional chaining
function obtenerCiudad(usuario) {
// tu codigo aqui
return usuario.direccion?.ciudad
}
console.log(obtenerCiudad({nombre: "Ana", edad: 28, email: "ana@example.com", direccion: {barrio: 'Belen Miravalle', ciudad: 'Medellin'}, profesion: 'Licenciada'}));
console.log(obtenerCiudad({nombre: "Ana", edad: 28, email: "ana@example.com", direccion: {barrio: 'Belen Miravalle'}, profesion: 'Licenciada'}));
console.log(obtenerCiudad({nombre: "Ana", edad: 28, email: "ana@example.com", profesion: 'Licenciada'}));
// --- Reto 6: Crear Producto
// Retorna un objeto con la siguiente estructura:
// id: 1
// nombre: "Laptop"
// precio: 999.99
// especificaciones: {
// marca: "TechBrand",
// memoria: "16GB",
// almacenamiento: "512GB SSD"
// }
function crearProducto() {
// tu codigo aqui
const producto = {nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
memoria: "16GB",
almacenamiento: "512GB SSD"}
}
return producto;
};
console.log(crearProducto());
// --- Reto 7: Obtener Memoria
// Recibe el objeto producto
// Retorna la propiedad:
// producto.especificaciones.memoria
// Debe retornar undefined si memoria no existe.
function obtenerMemoria(producto) {
// tu codigo aqui
return producto.especificaciones?.memoria;
}
console.log(obtenerMemoria({nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
memoria: "16GB",
almacenamiento: "512GB SSD"}
}));
console.log(obtenerMemoria({nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
bateria: "200mAp",
almacenamiento: "512GB SSD"}
}));
// --- Reto 8: Agregar Propiedad
// Recibe: objeto, nombrePropiedad y valor
// Agrega la propiedad al objeto y asígnale el valor.
// Retorna el objeto actualizado.
function agregarPropiedad(objeto, nombrePropiedad, valor) {
// tu codigo aqui
objeto[nombrePropiedad] = valor;
return objeto;
}
console.log(agregarPropiedad({nombre: "Laptop",
precio: 999.99,
especificaciones: {
marca: "TechBrand",
bateria: "200mAp",
almacenamiento: "512GB SSD"}
}, 'dueño', 'Pepito Perez'));
// --- Reto 9: Crear Calculadora
// Retorna un objeto con:
// valor: 0
//
// Métodos:
// sumar(num) => suma num al valor
// restar(num) => resta num al valor
// obtenerValor() => retorna el valor actual
//
// Pista:
// usa this.valor dentro de los métodos.
function crearCalculadora() {
// tu codigo aqui
;
return {
valor : 0,
sumar(num) {
this.valor = this.valor + num;
return this.valor;
},
restar(num) {
this.valor = this.valor - num;
return this.valor;
},
obtenerValor () {
return this.valor;
}
};
}
const miCalculadora = crearCalculadora();
console.log(miCalculadora.obtenerValor());
// --- Reto 10: Obtener Twitter
// Recibe un usuario (objeto)
// Retorna la propiedad: usuario.perfil.redes.twitter
// Si no existe debe retornar:
// "no-disponible"
//
// Pista:
// optional chaining + operador OR
function obtenerTwitter(usuario) {
// tu codigo aqui
return usuario.perfil?.redes?.twitter;
}
console.log(obtenerTwitter({nombre: "Ana", edad: 28, email: "ana@example.com", perfil: {redes: {instagram: 'pepita perez', feacebook: 'Florecita Florez', twitter: 'Fulanita de tal'}}}))
module.exports = {
crearUsuario,
obtenerNombre,
obtenerPropiedadDinamica,
tieneEmail,
obtenerCiudad,
crearProducto,
obtenerMemoria,
agregarPropiedad,
crearCalculadora,
obtenerTwitter,
};
// Un objeto es una colección "pares" clave y valor que permiten agrupar datos ¡cool!
const nota = { // Podemos crear un objeto o asignar un objeto atravez de nuestros "corchetes" "{}"
// ---! TODA ESTA INFORMACIÓN DENTRO DE LOS OBJETOS SON SUS CARACTERISTICAS ----!
id: 1, // Dentro de ella podemos hacer asignar primero una clave y luego su valor
title: "Mi primera nota", //Para definir el valor utilizamos ":" despues de asignar la clave
content : "clave",
creadeAt: Date.now() //Recuerda que tambien podemos utilizar el atributo de Date.now() para obtener el momento exacto en tiempo de algo en particular
}
// !---- ¿Como podemos obtener su información? ----!
console.log(nota.content); // Primero colocamos el nombre de nuestro objeto y "para acceder a sus propiedades utilizamos un "." " luego colocamos la caracteristica que queremos obtener su información de nuestro querio objeto
console.log(nota.title);
// !--- TENEMOS UNA SEGUNDA MANERA DE LLAMAR A UN OBJETO ¿cual es? ----!
// Podemos acceder al valor de nuestro objeto atravez de los "corchetes"
const campo = "content" // A una variable podemos asignarle el nombre de una clave de nuestro objeto :)
// El valor de la variable campo va a actuar como el nombre de la clave de nuestro objeto
console.log(nota[campo]); // Atravez de los corchetes es como si estuviramos escribiendo nuestro querio "." pero ahora con nuestros corchetes y el valor de nuestra variable el cual va a actuar como la clave de nuestro objeto.
// Entendiste Jeremy? :3
// !--- ¿Como evitamos problemas de objetos, variables etc no existentes y que arruines nuestra aplicación? -----!
// Atravez de la ¿letra? "?" podemos decirle a Javascript que no estamos seguros que el valor que estemos asignando a nuestras funciones exista o no?.
//Entonces si JavaScript detecta que no existe simplemente no la va a ejecutar de esa forma empidiendo que nuestra aplicación falle
//De la misma si la detecta la va ejecutar su función respectiva dentro de nuestro codigo ¡increible!
console.log(nota.author?.nombre); //Aquí tenemos un ejemplo claro el objeto de author dentro de nuestro objeto nota no existe.
//Así que javascript va a detectar que author no existe así que no va a ejecutar el console.log y mucho menos la propiedad nombre dentro de ella -_-
Mi solución:
// ============================================
// Reto 17: Objetos en JavaScript
// ============================================
// Completa cada función según las instrucciones.
// Ejecuta los tests con:
// npx vitest src/17-objetos-javascript
// ============================================
// --- Reto 1: Crear Usuario
// Crea y retorna un objeto con las siguientes propiedades:
// nombre: "Ana", edad: 28, email: "ana@example.com"
function crearUsuario() {
// tu codigo aquí
return {
nombre: 'Ana',
edad: 28,
email: 'ana@example.com'
}
}
// --- Reto 2: Obtener Nombre
// Recibe un usuario (objeto)
// Retorna la propiedad "nombre" del objeto usuario.
function obtenerNombre(usuario) {
// tu codigo aqui
return usuario.nombre;
}
// --- Reto 3: Obtener Propiedad Dinámica
// Recibe: objeto y propiedad
// Retorna el valor de la propiedad indicada.
// Pista: usa acceso con corchetes []
function obtenerPropiedadDinamica(objeto, propiedad) {
// tu codigo aqui
return objeto[propiedad];
}
// --- Reto 4: Tiene Email
// Recibe un usuario (objeto)
// Retorna true si el objeto tiene la propiedad "email"
// Retorna false si no existe.
// Pista: usa hasOwnProperty()
function tieneEmail(usuario) {
// tu codigo aqui
return usuario.hasOwnProperty('email');
}
// --- Reto 5: Obtener Ciudad
// Recibe un usuario (objeto)
// Retorna la ciudad dentro de: usuario.direccion.ciudad
// Si la propiedad no existe debe retornar undefined.
// Pista: optional chaining
function obtenerCiudad(usuario) {
// tu codigo aqui
return usuario.direccion?.ciudad;
}
// --- Reto 6: Crear Producto
// Retorna un objeto con la siguiente estructura:
// id: 1
// nombre: "Laptop"
// precio: 999.99
// especificaciones: {
// marca: "TechBrand",
// memoria: "16GB",
// almacenamiento: "512GB SSD"
// }
function crearProducto() {
// tu codigo aqui
return {
id: 1,
nombre: 'Laptop',
precio: 999.99,
especificaciones: {
marca: 'TechBrand',
memoria: '16GB',
almacenamiento: '512GB SSD'
}
}
}
// --- Reto 7: Obtener Memoria
// Recibe el objeto producto
// Retorna la propiedad:
// producto.especificaciones.memoria
// Debe retornar undefined si memoria no existe.
function obtenerMemoria(producto) {
// tu codigo aqui
return producto.especificaciones?.memoria;
}
// --- Reto 8: Agregar Propiedad
// Recibe: objeto, nombrePropiedad y valor
// Agrega la propiedad al objeto y asígnale el valor.
// Retorna el objeto actualizado.
function agregarPropiedad(objeto, nombrePropiedad, valor) {
// tu codigo aqui
objeto[nombrePropiedad] = valor;
return objeto;
}
// --- Reto 9: Crear Calculadora
// Retorna un objeto con:
// valor: 0
//
// Métodos:
// sumar(num) => suma num al valor
// restar(num) => resta num al valor
// obtenerValor() => retorna el valor actual
//
// Pista:
// usa this.valor dentro de los métodos.
function crearCalculadora() {
// tu codigo aqui
return {
valor: 0,
sumar(num) {
this.valor += num;
},
restar(num) {
this.valor -= num;
},
obtenerValor() {
// this.valor es otra cosa por completo: no es una búsqueda en el scope, es "búscame la propiedad valor en el objeto sobre el que me llamaron".
return this.valor;
}
}
}
// --- Reto 10: Obtener Twitter
// Recibe un usuario (objeto)
// Retorna la propiedad: usuario.perfil.redes.twitter
// Si no existe debe retornar:
// "no-disponible"
//
// Pista:
// optional chaining + operador OR
function obtenerTwitter(usuario) {
// tu codigo aqui
return usuario.perfil?.redes?.twitter || 'no-disponible';
}
console.log(obtenerTwitter({nombre:'Ana'}))
module.exports = {
crearUsuario,
obtenerNombre,
obtenerPropiedadDinamica,
tieneEmail,
obtenerCiudad,
crearProducto,
obtenerMemoria,
agregarPropiedad,
crearCalculadora,
obtenerTwitter,
};
Todos los test pasaron en verde 💚:

Por si alguien quiero ahondar mas en Optional Chaining existe en Kotlin algo que se llama Null Safety.
Comparto mi código con unas notas que añadí
/*Crea un objeto llamado usuario
Debe tener:
nombre
edad
email
Retorna ese objeto */
function crearUsuario() {
const usuario={
nombre:'Ana',
edad:27,
email:'ana@platzi.com'
};
return usuario;
}
// Recibe un objeto usuario
// Retorna solo el nombre
// Usa notación con punto
function obtenerNombre(usuario) {
// tu código aquí
return usuario.nombre;
}
// propiedad es un string (ej: "nombre")
// Accede usando corchetes []
// Retorna el valor correspondiente
function obtenerPropiedadDinamica(objeto, propiedad) {
// tu código aquí
return objeto[propiedad];
}
// Verifica si existe la propiedad "email"
// Usa un método de objetos (pista: hasOwnProperty)
//hasOwnProperty es tu filtro de seguridad para objetos.
// Imagina que quieres saber si un objeto tiene una propiedad suya,
// sin mirar lo que heredó del prototipo. Es como revisar qué herramientas
// tienes en tu propia caja, ignorando las que te prestó el vecino.
//Si usaras in o un simple if (user.toString),
// JavaScript buscaría en toda la cadena de prototipos y te daría un true confuso.
// hasOwnProperty corta el ruido y te da la certeza absoluta de que la llave pertenece
// a ese objeto específico.
function tieneEmail(usuario) {
// tu código aquí
return usuario.hasOwnProperty('email');
//Las comillas son necesarias porque hasOwnProperty espera recibir el nombre de la propiedad como un texto (un string).
// cuando usas métodos como hasOwnProperty, le estás enviando un parámetro. Ese parámetro debe ser el nombre exacto de la llave que buscas.
// Si no usaras las comillas, JavaScript intentaría buscar una variable con ese nombre en lugar de buscar la propiedad en el objeto.
//Las comillas le dicen a JavaScript: "esto es el nombre, no una variable".
}
Reto 5: Acceso seguro (optional chaining)
// Accede a:
// usuario.direccion.ciudad
// Pero sin romper si no existe
// Usa ?.
function obtenerCiudad(usuario) {
// tu código aquí
//pon el ? justo antes de cada punto donde sospeches que el valor anterior podría ser null o undefined.
return usuario?.direccion?.ciudad;
// El primero usuario? protege por si usuario ni siquiera existe (es null).
// Si no existe, ahí se detiene y devuelve undefined.
// El segundo direccion? protege por si el usuario existe, pero no tiene una propiedad direccion.
// Básicamente, el ? le dice a JavaScript: "Oye, intenta acceder a lo siguiente,
// pero si lo que está a la izquierda no existe, no explotes; simplemente ríndete y devuelve undefined".
//Es mejor prevenir que depurar
}
//Reto 6: Objeto anidado
// Crea un objeto producto
// Incluye:
// id, nombre, precio
// un objeto interno especificaciones
// Dentro de especificaciones agrega:
// marca, memoria, almacenamiento
function crearProducto() {
// tu código aquí
const producto={
id: 1,
nombre:'nombre',
precio:100,
especificaciones:{
marca: 'marca',
memoria: 'memoria',
almacenamiento:'almacenamiento'
}
};
return producto;
// Claves: Puedes omitir comillas (ej. id: 1).
// Valores: Si es texto, siempre lleva comillas (ej. nombre: 'Juan'). Si es número o booleano, no.
}
// Reto 7: Acceso a objeto anidado
// Accede a memoria
// Está dentro de especificaciones
// Usa ?. para evitar errores
function obtenerMemoria(producto) {
// tu código aquí
return producto?.especificaciones?.memoria;
}
// Reto 8: Agregar propiedad dinámica
// Agrega una nueva propiedad al objeto
// El nombre viene en una variable
// Usa []
// Retorna el objeto actualizado
function agregarPropiedad(objeto, nombrePropiedad, valor) {
// tu código aquí
objeto[nombrePropiedad]=valor;
// Al usar los corchetes [], le dices a JavaScript:
// "No busques una propiedad que se llame literalmente 'nombrePropiedad',
// busca el valor que tiene esa variable y úsalo como nombre".
// los corchetes son el puente entre una variable y una propiedad del objeto.
return objeto;
// Si escribes objeto.nombre, le estás diciendo a JavaScript:
// "Busca la propiedad que se llama literalmente 'nombre'".
// Es como si tuvieras una etiqueta pegada en el objeto.
// Pero si tienes una variable, como let clave = 'nombre', y haces objeto[clave], JavaScript hace esto:
// Mira qué hay dentro de clave (en este caso, la palabra 'nombre').
// Va al objeto y busca la propiedad que coincida con ese valor.
}
//Reto 9: Objeto con métodos
// propiedad valor (empieza en 0)
// método sumar(numero)
// método restar(numero)
// método obtenerValor()
function crearCalculadora() {
// tu código aquí
const calculadora={
valor:0,
sumar(numero) {
this.valor += numero;
return this; // simplificado
},
restar: function(numero){
return this.valor-=numero;
},
obtenerValor:function(){
return this.valor;
}
};
return calculadora;
}
// Reto 10: Acceso profundo + fallback
// Accede a:
// usuario.perfil.redes.twitter
// Usa ?.
// Si no existe → retorna "no-disponible"
function obtenerTwitter(usuario) {
// tu código aquí
return usuario?.perfil?.redes?.twitter || 'no-disponible';
}
// usuario?.perfil?.redes?.twitter: El ?. (optional chaining) va navegando por el objeto.
// Si en algún punto —ya sea que usuario no exista, o que no tenga perfil, o que perfil no tenga redes— la cadena se rompe,
// JavaScript no lanza un error. Simplemente se detiene y devuelve undefined.
// || 'no-disponible': Esto es el operador OR.
// Si la parte izquierda resulta ser undefined (o cualquier valor "falso"),
// el código salta automáticamente a lo que está a la derecha del ||.
// En JavaScript, el operador || evalúa la parte izquierda. Si esa parte es "verdadera" (tiene un valor real),
// se queda con ella. Pero si es "falsa" (como undefined, null, 0, o una cadena vacía),
// el operador dice: "Bueno, esto no me sirve, así que tomaré lo que está a la derecha".
module.exports = {
crearUsuario,
obtenerNombre,
obtenerPropiedadDinamica,
tieneEmail,
obtenerCiudad,
crearProducto,
obtenerMemoria,
agregarPropiedad,
crearCalculadora,
obtenerTwitter,
};
Es poco pero es trabajo honesto amigos.