Unidad 7 · Lecciones 035-047
Objetos en JavaScript
Si tuvieras que elegir un solo tema de este curso para dominar, seria este. Un objeto agrupa en una sola variable toda la informacion de una cosa: un producto, un usuario, una cita. Casi todo lo que devuelve una base de datos o una API llega en forma de objeto.
🎯 Objetivo de aprendizaje
Al terminar sabras crear objetos, leer y modificar sus valores, extraerlos con destructuring
(incluso anidados), protegerlos con freeze y seal, unir dos objetos,
anadirles funciones usando this y recorrer sus llaves y valores.
7.1 Crear un objeto
Imagina que quieres describir un producto. Sin objetos necesitas tres variables sueltas:
const nombre = 'Monitor de 20 pulgadas';
const precio = 300;
const disponible = true;
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
console.log(producto);
La sintaxis, parte por parte
- { }
- Las llaves delimitan el objeto. Si ves
= {, es un objeto.
- nombre
- Se llama propiedad o llave (key). Es el identificador del dato.
- :
- Dentro de un objeto se asigna con dos puntos, no con
=.
- ,
- Cada par llave-valor se separa con coma. Nunca con punto y coma.
⚠ Los dos errores tipicos
- Usar
=en vez de:dentro del objeto. - Separar las propiedades con
;en vez de,.
Esta forma de crear objetos se llama object literal. Hay otra, el object constructor, que veras en la seccion 7.10.
7.2 Acceder a los valores
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
// 1. Sintaxis de PUNTO: la habitual
console.log(producto.nombre);
console.log(producto.precio);
console.log(producto.disponible);
// 2. Sintaxis de CORCHETES: menos comun, pero util en algunos casos
console.log(producto['nombre']);
💡 Cuando usar los corchetes
La sintaxis de punto es la normal. Los corchetes son necesarios cuando el nombre de la propiedad
esta guardado en una variable o contiene caracteres raros. Lo veras en accion
con for...in en la Unidad 11.
7.3 Anadir y eliminar propiedades
Puedes anadir propiedades despues de crear el objeto, mientras el programa se
ejecuta. La sintaxis es la misma de punto, pero ahora con = porque estas fuera
de las llaves.
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
// Fuera del objeto se usa = , no :
producto.imagen = 'imagen.jpg';
console.log(producto);
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
delete producto.disponible;
console.log(producto); // ya no aparece disponible
💡 Caso real
Cuando consultas un usuario en una base de datos, te devuelve el objeto completo, incluida su
contrasena cifrada. Antes de enviar esos datos al navegador, se hace
delete usuario.password. Es un uso cotidiano de delete.
7.4 Destructuring de objetos
Muy a menudo quieres sacar un valor del objeto y guardarlo en su propia variable. La forma antigua exige dos pasos:
const nombre = producto.nombre; // crear variable + extraer valor
console.log(nombre);
ECMAScript 6 introdujo el destructuring (extraer de una estructura), que hace las dos cosas en un solo paso:
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
// Las llaves a la IZQUIERDA del = indican destructuring
const { nombre } = producto;
console.log(nombre);
💡 Como reconocerlo
Cuando veas const { algo } = objeto, con llaves al lado izquierdo del igual,
estas viendo destructuring. Es una senal inequivoca.
Extraer varios valores a la vez
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
const { nombre, precio, disponible } = producto;
console.log(nombre);
console.log(precio);
console.log(disponible);
const producto = { nombre: 'Monitor', precio: 300 };
const { descuento } = producto;
console.log(descuento); // undefined: la variable se crea, pero sin valor
+ Por que importa tanto
El curso original se regrabo entero en buena parte por el destructuring: cuando se grabo la primera version, muchas librerias y frameworks todavia no lo soportaban bien. Hoy es la forma estandar de trabajar con datos en React, Vue y practicamente cualquier proyecto moderno.
7.5 Objetos dentro de objetos
El valor de una propiedad puede ser otro objeto. Asi se construyen estructuras tan complejas como necesites:
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true,
informacion: {
medidas: {
peso: '1kg',
medida: '1m'
},
fabricacion: {
pais: 'China'
}
}
};
console.log(producto);
Acceder a lo que hay dentro
Se encadenan puntos, un nivel por punto:
const producto = {
nombre: 'Monitor de 20 pulgadas',
informacion: {
medidas: { peso: '1kg', medida: '1m' },
fabricacion: { pais: 'China' }
}
};
console.log(producto.informacion); // el objeto entero
console.log(producto.informacion.medidas); // un nivel mas
console.log(producto.informacion.medidas.peso); // '1kg'
console.log(producto.informacion.fabricacion.pais); // 'China'
✗ Si accedes a algo que no existe
producto.informacion.garantia.meses lanzara un error: JavaScript no puede leer la
propiedad meses de algo que vale undefined. Es uno de los errores mas
frecuentes al trabajar con datos de una API.
7.6 Destructuring de objetos anidados
Aqui la sintaxis se complica. La regla es: para bajar un nivel, se usan dos puntos y se abren llaves de nuevo.
const producto = {
nombre: 'Monitor de 20 pulgadas',
informacion: {
medidas: { peso: '1kg', medida: '1m' },
fabricacion: { pais: 'China' }
}
};
// "Entra en informacion y saca fabricacion"
const { informacion: { fabricacion } } = producto;
console.log(fabricacion); // { pais: 'China' }
⚠ El detalle que confunde a todo el mundo
En el ejemplo anterior, la variable informacion no se crea.
Los dos puntos significan «entra aqui», no «crea esta variable».
Si intentas hacer console.log(informacion) obtendras un error.
Crear tambien la variable intermedia
const producto = {
informacion: {
medidas: { peso: '1kg' },
fabricacion: { pais: 'China' }
}
};
// Anadir "informacion," antes crea tambien esa variable
const { informacion, informacion: { fabricacion } } = producto;
console.log(informacion); // el objeto completo
console.log(fabricacion); // { pais: 'China' }
Bajar dos niveles
const producto = {
informacion: {
fabricacion: { pais: 'China' }
}
};
const { informacion: { fabricacion: { pais } } } = producto;
console.log(`Este articulo fue fabricado en ${pais}`);
💡 Como leerlo
Lee de fuera hacia dentro: «de producto, entra en informacion,
dentro entra en fabricacion, y de ahi saca pais».
Solo lo ultimo se convierte en variable.
7.7 El problema con const y los objetos
En la Unidad 2 aprendiste que una variable const no se puede reasignar. Con los
objetos eso es cierto... a medias.
const nombreProducto = 'Monitor';
nombreProducto = 'Tablet';
// TypeError: Assignment to
// constant variable
const producto = {
nombre: 'Monitor',
precio: 300,
disponible: true
};
producto.disponible = false; // se permite
delete producto.precio; // tambien
console.log(producto);
🎓 Pregunta de entrevista
¿Se pueden modificar los valores de una variable declarada con const?
Si, cuando es un objeto o un arreglo. const protege la
referencia (no puedes apuntar la variable a otra cosa), pero no el contenido.
Para proteger el contenido hay que usar Object.freeze() o Object.seal().
7.8 Proteger un objeto: freeze y seal
+ Primero: el modo estricto
Para que estos metodos avisen con un error en lugar de fallar en silencio, conviene activar el
modo estricto escribiendo 'use strict'; en la primera linea del
archivo. Es el equivalente del comparador === pero a nivel de documento: le dice a
JavaScript «no me permitas malas practicas aqui».
'use strict';
x = 20; // Sin modo estricto: JavaScript crea la variable por ti
console.log(x); // Con modo estricto: ReferenceError, x no esta definida
Object.freeze() — congelar
Deja el objeto tal cual esta: no se puede modificar, ni anadir, ni eliminar nada.
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
Object.freeze(producto);
// Comprobar si esta congelado
console.log(Object.isFrozen(producto)); // true
// Con 'use strict' activo, cualquier intento de cambio lanza un error.
// Los envolvemos en try/catch para poder ver los tres mensajes seguidos.
try { producto.disponible = false; }
catch (e) { console.error('Modificar: ' + e.message); }
try { producto.imagen = 'nueva.jpg'; }
catch (e) { console.error('Anadir: ' + e.message); }
try { delete producto.precio; }
catch (e) { console.error('Eliminar: ' + e.message); }
console.log(producto); // el objeto sigue exactamente igual
Object.seal() — sellar
Mas permisivo: si deja modificar las propiedades existentes, pero no anadir ni eliminar.
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
Object.seal(producto);
console.log(Object.isSealed(producto)); // true
// SI funciona: la propiedad ya existia
producto.disponible = false;
// NO: no se pueden anadir propiedades nuevas
try { producto.imagen = 'nueva.jpg'; }
catch (e) { console.error('Anadir: ' + e.message); }
// NO: no se pueden eliminar
try { delete producto.precio; }
catch (e) { console.error('Eliminar: ' + e.message); }
console.log(producto); // disponible ya es false, pero sigue teniendo precio
🎓 Pregunta de entrevista
| Modificar | Anadir | Eliminar | Comprobar con | |
|---|---|---|---|---|
Object.freeze() | No | No | No | Object.isFrozen() |
Object.seal() | Si | No | No | Object.isSealed() |
7.9 Unir dos objetos
Tarea muy comun: tienes los datos de un cliente en un objeto y su direccion en otro, y necesitas combinarlos. Hay dos formas.
const producto = { nombre: 'Monitor', precio: 300 };
const medidas = { peso: '1kg', medida: '1m' };
const resultado = Object.assign(producto, medidas);
console.log(resultado);
const producto = { nombre: 'Monitor', precio: 300 };
const medidas = { peso: '1kg', medida: '1m' };
const resultado2 = { ...producto, ...medidas };
console.log(resultado2);
💡 Que significan los tres puntos
...producto quiere decir «toma una copia de todo lo que hay dentro de
producto y colocalo aqui». Se llama spread operator
(o rest operator segun donde aparezca). La primera vez resulta poco intuitivo,
pero es la sintaxis mas usada hoy.
Lo volveras a ver con arreglos en las Unidades 8 y 12.
7.10 Funciones dentro de objetos y la palabra this
+ Nota sobre el orden
Las funciones se estudian en la Unidad 9. Aqui basta con saber que una funcion es un bloque de codigo que se ejecuta cuando lo llamas.
Una propiedad de un objeto puede tener como valor una funcion. Se le llama metodo:
const nombre = 'Hola';
const precio = 20;
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
mostrarInfo: function() {
console.log(`El producto ${nombre} tiene un precio de ${precio}`);
}
};
producto.mostrarInfo();
// "El producto Hola tiene un precio de 20"
// Esta leyendo las variables de FUERA, no las del objeto
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
mostrarInfo: function() {
console.log(`El producto ${this.nombre} tiene un precio de ${this.precio}`);
}
};
producto.mostrarInfo();
// "El producto Monitor de 20 pulgadas tiene un precio de 300"
💡 Que es this
this significa «este mismo objeto». Le dice a JavaScript
que busque la propiedad dentro del objeto en vez de salir a buscarla fuera.
Por que es imprescindible
Con dos objetos distintos se ve claramente que this mantiene cada uno en su sitio:
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
mostrarInfo: function() {
console.log(`El producto ${this.nombre} tiene un precio de ${this.precio}`);
}
};
const producto2 = {
nombre: 'Tablet',
precio: 3000,
mostrarInfo: function() {
console.log(`El producto ${this.nombre} tiene un precio de ${this.precio}`);
}
};
producto.mostrarInfo();
producto2.mostrarInfo();
⚠ this es palabra reservada
No puedes nombrar una variable this. El lenguaje ya la usa.
7.11 El Object Constructor
El object literal te obliga a escribir el objeto entero cada vez. Si vas a crear muchos objetos del mismo tipo, es mejor tener una plantilla: eso es un object constructor.
// La plantilla: por convencion se nombra con mayuscula inicial
function Producto(nombre, precio) {
this.nombre = nombre;
this.precio = precio;
this.disponible = true; // valor por defecto
}
// Crear objetos a partir de ella con la palabra new
const producto2 = new Producto('Monitor de 24 pulgadas', 500);
const producto3 = new Producto('Television', 100);
console.log(producto2);
console.log(producto3);
Que hace cada parte
function Producto(nombre, precio)— define la plantilla y los datos que necesita.this.nombre = nombre— guarda el valor recibido dentro del objeto que se esta creando. Sinthis, los valores se perderian o se mezclarian.new Producto(...)— crea un objeto nuevo a partir de la plantilla.
💡 Ya conocias esta sintaxis
new String(), new Number(), new Boolean()... es exactamente
el mismo mecanismo. Con un constructor estas creando tu propio «tipo de dato».
+ Contexto
Esta era la forma de hacer programacion orientada a objetos en JavaScript antes
de que el lenguaje incorporase las class. Aunque el constructor es mas dinamico,
en el dia a dia se usa mucho mas el object literal. Conviene conocer ambos.
7.12 Object.keys, values y entries
const producto = {
nombre: 'Monitor de 20 pulgadas',
precio: 300,
disponible: true
};
// keys -> las LLAVES (la parte izquierda)
console.log(Object.keys(producto));
// values -> los VALORES (la parte derecha)
console.log(Object.values(producto));
// entries -> ambos en PARES
console.log(Object.entries(producto));
- Object.keys()
- Devuelve un arreglo con los nombres de las propiedades.
- Object.values()
- Devuelve un arreglo con los valores.
- Object.entries()
- Devuelve un arreglo de parejas
[llave, valor].
El truco: saber si un objeto esta vacio
const clienteEncontrado = { nombre: 'Ana', email: 'ana@correo.com' };
const clienteVacio = {};
console.log(Object.keys(clienteEncontrado)); // ['nombre', 'email']
console.log(Object.keys(clienteEncontrado).length); // 2
console.log(Object.keys(clienteVacio)); // []
console.log(Object.keys(clienteVacio).length); // 0 -> esta vacio
Es la forma habitual de comprobar si una consulta a la base de datos devolvio algo o no.
Object.entries() volvera a aparecer en la Unidad 11
para recorrer objetos con for...of.
7.13 Ejercicios practicos
Llega hasta el pais
Con el objeto anidado de la seccion 7.5, accede al pais de fabricacion de dos maneras distintas: con sintaxis de punto y con destructuring anidado.
Ver solucion
const producto = {
nombre: 'Monitor de 20 pulgadas',
informacion: {
medidas: { peso: '1kg', medida: '1m' },
fabricacion: { pais: 'China' }
}
};
// Con sintaxis de punto
console.log(producto.informacion.fabricacion.pais);
// Con destructuring anidado
const { informacion: { fabricacion: { pais } } } = producto;
console.log(pais);
Ficha de cliente con metodo
Crea un objeto cliente con nombre, email y saldo. Anadele un metodo
mostrarResumen() que imprima los tres datos usando this y un template string.
Ver solucion
const cliente = {
nombre: 'Ana Lopez',
email: 'ana@correo.com',
saldo: 1250.5,
mostrarResumen: function() {
console.log(`Cliente: ${this.nombre}`);
console.log(`Contacto: ${this.email}`);
console.log(`Saldo disponible: ${this.saldo}`);
}
};
cliente.mostrarResumen();
Fusionar sin destruir
Tienes un objeto usuario y otro direccion. Combinalos en un tercer
objeto usando el spread operator, y demuestra que el objeto usuario original
no se ha modificado.
Ver solucion
const usuario = { nombre: 'Ana', email: 'ana@correo.com' };
const direccion = { ciudad: 'Guadalajara', pais: 'Mexico' };
const completo = { ...usuario, ...direccion };
console.log('Combinado:', completo);
console.log('Original:', usuario); // intacto: solo nombre y email
💡 Diferencia con Object.assign
Object.assign(usuario, direccion) si modifica el primer objeto,
porque lo usa como destino. El spread operator crea uno nuevo y deja los originales en paz.
Esa idea (no modificar los datos originales) es la base de la programacion funcional.
Catalogo con constructor
Crea un constructor Curso que reciba titulo, precio e instructor, y que anada
automaticamente publicado: true. Genera tres cursos, congela el primero,
intenta modificarlo y comprueba el resultado.
Ver solucion
function Curso(titulo, precio, instructor) {
this.titulo = titulo;
this.precio = precio;
this.instructor = instructor;
this.publicado = true;
}
const curso1 = new Curso('JavaScript Moderno', 12, 'Juan');
const curso2 = new Curso('React desde cero', 15, 'Ana');
const curso3 = new Curso('Node.js avanzado', 18, 'Luis');
console.log(curso1);
console.log(curso2);
console.log(curso3);
// Congelar el primero
Object.freeze(curso1);
console.log('Congelado?', Object.isFrozen(curso1));
try { curso1.precio = 0; }
catch (e) { console.error('No se pudo cambiar: ' + e.message); }
console.log('Precio tras intentar cambiarlo:', curso1.precio); // sigue 12
// Ver sus llaves y valores
console.log(Object.keys(curso1));
console.log(Object.values(curso1));
7.14 Resumen de lo aprendido
- Un objeto agrupa varios datos de una misma cosa. Se crea con llaves, se asigna con
:y se separa con,. - Acceso: sintaxis de punto (
producto.nombre) o de corchetes (producto['nombre']). - Modificar: fuera del objeto se usa
=. Para borrar,delete objeto.propiedad. - Destructuring:
const { nombre } = productocrea la variable y extrae el valor en un paso. - Anidado: los dos puntos bajan de nivel; solo la ultima llave se convierte en variable.
constno protege el contenido de un objeto: solo impide reasignar la variable.Object.freeze()impide todo cambio;Object.seal()permite modificar lo existente pero no anadir ni borrar.- Unir objetos:
Object.assign()(modifica el primero) o{ ...a, ...b }(crea uno nuevo). thisdentro de un metodo se refiere al propio objeto; sin el, JavaScript busca las variables fuera.- El object constructor es una plantilla para crear muchos objetos iguales con
new. Object.keys/values/entriesdevuelven arreglos con las llaves, los valores o ambos.
7.15 Verificacion de cierre
¿Que permite Object.seal() que Object.freeze() no permite?
- Anadir nuevas propiedades
- Eliminar propiedades
- Modificar las propiedades existentes
- Nada, son identicos
Tras const { informacion: { fabricacion } } = producto;, ¿que variables existen?
- Solo
informacion - Solo
fabricacion - Las dos
- Ninguna: es sintaxis invalida
¿Para que sirve this dentro de un metodo de objeto?
- Para que la propiedad se busque dentro del propio objeto
- Para congelar el objeto y que no se modifique
- Para convertir el objeto en un arreglo
- Para crear una copia del objeto
🏁 Unidad completada