- Aprender
- Informática
- Programación
- Programación en JavaScript
- Objetos y JSON en JavaScript
Objetos y JSON en JavaScript: propiedades, métodos y this
PrincipianteUnidad 4 de 9 del curso Curso de Programación en JavaScript
Lo que aprenderás
- Describe cosas reales en código como objetos con propiedades nombradas, lee y modifica esas propiedades y comprende cómo se almacenan, copian y comparan los objetos.
- Crea objetos y trabaja con sus propiedadesEscribe literales de objeto, lee propiedades con la notación de punto y de corchetes, y añade, modifica y elimina propiedades.
- Comprueba y recorre las propiedades de un objetoComprueba si existe una propiedad, enumera claves, valores y entradas, y recorre o transforma las propiedades de un objeto.
- Comprende las referencias, las copias y la comparaciónExplica por qué los objetos se comparten por referencia, compara objetos correctamente y crea copias superficiales y profundas.
- Trabaja con datos anidadosLee y procesa objetos dentro de objetos y arrays de objetos, protégete frente a partes ausentes con ?. y ??, y elige una estructura que se ajuste a los datos.
- Crea objetos y trabaja con sus propiedades
- Escribe métodos que usen los datos de su objeto, explica cómo obtiene su valor la palabra clave this en cada tipo de llamada y conserva el this correcto al pasar un método.
- Escribe métodos que usen los datos de su objetoDefine métodos con la sintaxis abreviada, usa this para leer y actualizar el objeto y llama a los métodos correctamente.
- Explica cómo obtiene this su valorDetermina el valor de this a partir de cómo se llama a una función y explica por qué las funciones flecha se comportan de manera diferente.
- Conserva this al pasar métodos como funciones de devolución de llamadaReconoce cuándo un método pierde su objeto y corrígelo con una función envolvente de tipo flecha, bind, call o apply.
- Escribe métodos que usen los datos de su objeto
- Extrae valores de objetos y arrays con desestructuración, y copia, combina y recopila valores con la sintaxis de propagación y resto.
- Desestructura objetosExtrae propiedades de objetos en variables, con cambio de nombre, valores predeterminados, patrones anidados y parámetros de función desestructurados.
- Desestructura arrays y otros iterablesExtrae valores por posición, omítelos y establece valores predeterminados, intercambia variables y desestructura entradas en bucles.
- Copia, combina y recopila datos con propagación y restoUsa la propagación para copiar y combinar objetos y arrays y para pasar elementos de arrays como argumentos, usa el resto para recopilar valores y distingue ambos usos.
- Desestructura objetos
- Usa Map para colecciones de pares clave-valor con claves de cualquier tipo y Set para colecciones de valores únicos, y elige entre ellos y los objetos y arrays ordinarios.
- Almacena pares clave-valor en un MapCrea y actualiza un Map, recorre sus entradas, convierte entre Map y objetos y decide cuándo un Map es más adecuado que un objeto.
- Conserva valores únicos en un SetCrea y actualiza un Set, elimina duplicados de arrays y compara colecciones mediante operaciones de conjuntos.
- Almacena pares clave-valor en un Map
- Lee y escribe el formato de texto JSON, convierte valores de JavaScript a JSON con JSON.stringify y texto JSON de nuevo a valores con JSON.parse, y maneja los casos en que no coinciden.
- Lee y escribe en formato JSONReconoce JSON válido, explica en qué se diferencia de un literal de objeto de JavaScript y detecta errores de sintaxis habituales.
- Convierte valores en texto JSON con JSON.stringifyConvierte objetos y arrays en cadenas JSON, da formato al resultado, elige qué propiedades incluir y predice qué se omite o cambia.
- Convierte texto JSON en valores con JSON.parseAnaliza JSON de forma segura, restaura valores como fechas con una función de transformación, comprueba los datos analizados y conviértelos de ida y vuelta mediante JSON.
- Lee y escribe en formato JSON
Guía de estudio de Objetos y JSON en JavaScript
1Modela datos con objetos
Un objeto mantiene juntos valores relacionados bajo nombres, de modo que un registro puede describir un libro, una persona o una lectura. Trabajar con esos nombres te permite modificar un campo, examinar un registro completo y organizar listas de registros. También seguirás qué variables apuntan al mismo objeto. Esa distinción importa cuando un cambio aparece en dos lugares, una copia contiene datos anidados o un campo ausente necesita un valor predeterminado razonable.
1.1 Crea objetos y trabaja con sus propiedades
Un objeto agrupa valores relacionados bajo nombres. Cada propiedad asocia una clave con un valor. Usa un objeto para un registro y un array de objetos para una lista ordenada. Los arrays paralelos pueden dejar de corresponderse cuando solo se ordena o modifica uno de ellos.
Crea y lee un registro
const book = { title: "Dune", pages: 412, available: true };
book.title; // "Dune"
book["title"]; // "Dune"
Los valores de las propiedades pueden ser arrays, objetos o funciones, además de valores primitivos. Las claves son cadenas o símbolos; estos ejemplos usan cadenas. Las claves de cadena que son identificadores válidos no necesitan comillas. Las claves que contienen espacios o guiones necesitan comillas: { "release-year": 1965 }. Las claves numéricas se convierten en cadenas, por lo que { 1: "a" } tiene la clave "1". Los literales de objeto permiten una coma final.
El acceso con punto usa el nombre literal después del punto. El acceso con corchetes evalúa una expresión:
const field = "pages";
book[field]; // 412
book.field; // undefined
La segunda expresión busca una propiedad llamada "field". Los corchetes también permiten usar book["release-year"]. Una propiedad ausente devuelve undefined; seguir accediendo a través de ella, como en book.author.name, lanza un TypeError cuando falta la propiedad del autor.
Modifica el contenido del objeto
book.author = "Frank Herbert";
book.pages = 896;
delete book.available;
La asignación añade una propiedad ausente o sustituye un valor existente. La eliminación quita la propia propiedad, por lo que "available" in book ahora es falso. const mantiene la variable vinculada a este objeto, pero permite modificar su contenido.
Para const reading = { city: "Nairobi", tempC: 24.5 };, reading.tempC += 1.5; almacena 26. Después, reading.humidity = 61; añade un campo. Con const key = "humidity";, reading[key] lee 61. Un nombre como tempC hace visible la unidad de la medición.
Usa variables en un literal
const name = "Lena";
const age = 29;
const person = { name, age };
const lang = "nl";
const greeting = { [lang]: "Hallo" };
La sintaxis abreviada { name, age } significa { name: name, age: age }. Un nombre calculado evalúa la expresión dentro de los corchetes: greeting tiene la propiedad "nl". Sin esos corchetes, { lang: "Hallo" } crearía la clave literal "lang".
Puntos clave
- Un objeto agrupa valores relacionados en propiedades nombradas.
- Usa corchetes para una clave almacenada en una variable o que contiene un guion.
- La asignación añade o sustituye una propiedad;
deletela elimina. constfija la variable, no el contenido del objeto.- La sintaxis abreviada toma el valor de una variable; una clave calculada evalúa una expresión.
1.2 Comprueba y recorre las propiedades de un objeto
Comprobar si existe un campo es distinto de comprobar su valor. Una cadena vacía, cero o false pueden ser valores almacenados perfectamente válidos.
Plantea la pregunta adecuada sobre la existencia
const item = { stock: 0, note: undefined };
Object.hasOwn(item, "stock"); // true
"note" in item; // true
Boolean(item.stock); // false
Object.hasOwn(obj, key) comprueba solo las propiedades propias del objeto. El operador in también comprueba las propiedades heredadas: "toString" in {} es true, mientras que Object.hasOwn({}, "toString") es false. El código más antiguo suele llamar a obj.hasOwnProperty(key).
Una condición como if (item.stock) comprueba si el valor es verdadero en contexto booleano. No puede distinguir un campo ausente de uno presente que contiene cero. El mismo problema se aplica a "", false, null, undefined y NaN. Incluso un valor undefined puede pertenecer a una propiedad existente, como ocurre con note arriba.
Elige claves, valores o pares
Para const scores = { Ana: 82, Ben: 74, Chen: 91 };, estas funciones devuelven arrays de las propiedades propias y enumerables con claves de cadena:
| Expresión | Resultado |
|---|---|
Object.keys(scores) | ["Ana", "Ben", "Chen"] |
Object.values(scores) | [82, 74, 91] |
Object.entries(scores) | [["Ana", 82], ["Ben", 74], ["Chen", 91]] |
El objeto no tiene una longitud como la de un array: scores.length es undefined. Object.keys(scores).length cuenta tres propiedades. Para sumar las puntuaciones, reduce los valores con un cero inicial. Su suma es 247 y su media es aproximadamente 82,33.
Recorre con ambas partes disponibles
let bestName;
let bestScore = -Infinity;
for (const [name, score] of Object.entries(scores)) {
if (score > bestScore) {
bestName = name;
bestScore = score;
}
}
El bucle compara 82, 74 y después 91 con la mejor puntuación encontrada hasta ese momento. Termina con "Chen" y 91. El patrón de corchetes da nombres a las dos partes de cada par.
Un objeto ordinario no es iterable, por lo que for...of scores lanza un TypeError. Object.entries(scores) proporciona un array iterable. El bucle más antiguo for...in produce claves de cadena y puede incluir propiedades heredadas enumerables.
Transforma las entradas de nuevo en un objeto
const weightsG = { flour: 500, sugar: 250, salt: 5 };
const weightsKg = Object.fromEntries(
Object.entries(weightsG).map(([item, g]) => [item, g / 1000])
);
entries produce pares, map cambia cada valor y conserva su clave, y fromEntries reconstruye el registro. El resultado es { flour: 0.5, sugar: 0.25, salt: 0.005 }; weightsG permanece sin cambios.
El orden de las propiedades propias está definido. Las claves de índice de array desde "0" hasta "4294967294" aparecen primero en orden ascendente; las demás claves de cadena siguen el orden de inserción. Un cero inicial, como en "01", impide que una clave sea un índice de array. Así, Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }) da ["1", "2", "b", "a"]. Usa un array cuando las posiciones tengan significado.
Puntos clave
- La existencia de una propiedad y su valor en contexto booleano responden a preguntas distintas.
Object.hasOwncomprueba las propiedades propias;intambién comprueba las heredadas.Object.entriesproporciona pares clave-valor para bucles y transformaciones.Object.fromEntriesreconstruye un objeto a partir de pares.- Las claves de índice de array preceden a las demás claves de cadena en el orden de las propiedades.
- Cuenta las claves de cadena propias y enumerables con
Object.keys(obj).length.
1.3 Comprende las referencias, las copias y la comparación
Dos variables pueden hacer referencia a un mismo objeto. Antes de predecir una actualización, determina si el código creó un objeto nuevo o copió una referencia a uno existente.
Sigue la identidad por separado de los datos
const p1 = { x: 1 };
const p2 = p1;
p2.x = 99;
p1.x; // 99
p1 === p2; // true
La asignación copió la referencia. Ambos nombres acceden a la misma propiedad. La asignación de valores primitivos funciona de otra manera: después de let a = 5; let b = a; b = 6;, a sigue siendo 5.
Los objetos se comparan por identidad tanto con === como con ==. Dos literales crean objetos separados aunque todos sus campos coincidan: ({ x: 1 } === { x: 1 }) es false. Para comparar sus datos, compara las propiedades pertinentes. Que se muestren de la misma forma no comprueba su identidad.
Pasar un objeto a una función también copia su referencia. Una función que ejecuta order.status = "shipped"; modifica el objeto de quien la llama. Devolver { ...order, status: "shipped" } en su lugar crea un registro nuevo en el nivel superior.
Distingue const, la congelación y la copia
const cart = { items: 2 }; permite cart.items = 3;, pero la reasignación cart = {}; lanza un TypeError. Object.freeze(cart) bloquea los cambios en sus propiedades propias. En modo estricto, los intentos de añadirlas, eliminarlas o sobrescribirlas lanzan un TypeError.
La congelación es superficial. Si un registro congelado contiene otro objeto, los campos de ese objeto anidado aún pueden cambiar. Un contenedor congelado y una estructura que no puede modificarse en profundidad son cosas distintas.
Sigue una copia superficial
const settings = { theme: "dark", font: { size: 14 } };
const copy = { ...settings };
copy.theme = "light";
copy.font.size = 18;
La propagación crea un objeto externo nuevo. Su valor theme se copia, por lo que cambiar copy.theme deja settings.theme como "dark". Su valor font es una referencia que se copia en ambos registros. Por tanto, actualizar copy.font.size hace que settings.font.size también sea igual a 18.
Object.assign({}, settings) también crea una copia superficial. Una copia superficial separa el registro externo, pero conserva la identidad de los objetos y arrays anidados.
Copia los datos anidados cuando deban ser independientes
const deep = structuredClone(settings);
deep.font.size = 22;
settings.font.size; // 18
structuredClone copia objetos y arrays anidados, junto con valores compatibles como Map, Set y Date. También maneja referencias circulares. El nuevo font anidado puede cambiar de forma independiente. Las funciones no se pueden clonar de este modo: un objeto que contiene un método provoca un DataCloneError.
Una conversión de ida y vuelta mediante JSON, JSON.parse(JSON.stringify(obj)), copia solo datos compatibles con JSON. Omite las propiedades de objeto que contienen undefined o funciones, convierte fechas en cadenas y pierde las entradas de Map y Set salvo que las conviertas. Elige una clonación para obtener datos de JavaScript compatibles e independientes, y elige JSON cuando quieras crear una representación de texto.
Puntos clave
- Las asignaciones y las llamadas a funciones copian referencias a objetos.
- Los objetos se comparan por identidad, incluso cuando sus campos coinciden.
- Una copia superficial comparte los objetos anidados.
Object.freezebloquea los cambios en propiedades propias, pero es superficial.structuredClonecopia datos anidados compatibles y rechaza funciones.
1.4 Trabaja con datos anidados
Los datos anidados combinan registros y listas. Lee una ruta paso a paso y comprueba si cada paso llega a un objeto, un array o un valor final.
Lee y procesa una lista dentro de un registro
const order = {
id: 1042,
customer: { name: "Sara", city: "Lisbon" },
items: [
{ product: "Tea", qty: 2, unitPrice: 4.5 },
{ product: "Mug", qty: 1, unitPrice: 9 }
]
};
order.customer.city lee "Lisbon". order.items[1].product selecciona primero el array de artículos, después su segundo registro y luego "Mug". order.items.length es 2.
Los métodos de array que ya conoces funcionan con propiedades de registros. map(item => item.product) produce nombres de productos. filter(item => item.qty > 1) conserva la línea del té. find(item => item.product === "Mug") devuelve el registro existente de la taza, por lo que modificar el registro devuelto modifica el artículo del pedido.
Para calcular el total, usa order.items.reduce((sum, item) => sum + item.qty * item.unitPrice, 0). La primera línea suma 9; la segunda suma otros 9, lo que da 18. Calcular un total cuando se necesita evita que un total almacenado por separado quede desactualizado cuando cambian los artículos.
Lee datos opcionales con una alternativa de respaldo
order.shipping?.date; // undefined
order.customer?.city ?? "unknown"; // "Lisbon"
El encadenamiento opcional, ?., se detiene cuando el valor inmediatamente a su izquierda es null o undefined. Un acceso directo con order.shipping.date lanzaría un TypeError. Usa una comprobación en cada enlace opcional de una ruta más larga. El acceso con corchetes y las llamadas también lo admiten: order.items?.[0] y order.print?.().
El encadenamiento opcional es para valores que pueden faltar. Los campos obligatorios siguen necesitando comprobaciones o errores que revelen un registro incorrecto. No puede aparecer a la izquierda de una asignación: order.shipping?.date = "2026-05-01" es un error de sintaxis.
El operador de coalescencia nula, ??, usa su lado derecho solo para null o undefined. Conserva cero, false y "". Para const qty = 0;, qty ?? 1 sigue siendo cero, mientras que qty || 1 pasa a ser 1 porque || sustituye todos los valores falsos en contexto booleano.
Elige una estructura útil
Un array de registros es adecuado para enumerar, filtrar y ordenar. Un objeto con claves basadas en ID permite la búsqueda directa: usersById["u23"].name. Un Map es útil cuando las claves de búsqueda se añaden y eliminan con frecuencia.
El JavaScript más reciente ofrece Object.groupBy, ampliamente disponible desde 2024:
const tasks = [
{ title: "Book flights", status: "done" },
{ title: "Pack", status: "todo" },
{ title: "Renew passport", status: "done" }
];
const grouped = Object.groupBy(tasks, task => task.status);
grouped.done contiene dos registros y grouped.todo contiene uno. El resultado no tiene prototipo, por lo que no tiene un método toString heredado. Una alternativa más antigua construye los arrays explícitamente para estas claves de estado:
const groupedOlder = tasks.reduce((groups, task) => {
if (!Object.hasOwn(groups, task.status)) {
groups[task.status] = [];
}
groups[task.status].push(task);
return groups;
}, {});
El primer registro de cada grupo crea su array. Los registros posteriores se añaden a ese mismo array. Este acumulador es un objeto ordinario; el resultado del método más reciente no tiene prototipo. Usa nombres y tipos de valor coherentes entre los registros; nombres como distanceKm y tempC también mantienen visibles las unidades.
Puntos clave
- Lee una ruta anidada desde su objeto externo hacia el valor necesario.
finddevuelve el registro existente, no una copia.?.se detiene ante un enlace nulo o indefinido;??proporciona una alternativa en ese caso.- Usa un array para una lista ordenada y datos con claves para la búsqueda directa.
Object.groupByagrupa registros en arrays bajo claves.- Los nombres de campos, tipos y unidades coherentes facilitan el procesamiento de los registros.
2Da comportamiento a los objetos con métodos y this
Los métodos permiten que un objeto combine sus datos con acciones que los usan. La pequeña palabra this conecta una acción con un objeto, pero su valor depende de cómo se ejecuta la función. Seguirás llamadas ordinarias a métodos, métodos prestados y funciones de devolución de llamada, y después elegirás una función envolvente o una función vinculada cuando una acción deba conservar su objeto. Los ejemplos se ejecutan como módulos, por lo que se aplica el modo estricto salvo que un ejemplo use explícitamente código no estricto.
2.1 Escribe métodos que usen los datos de su objeto
Un método es una propiedad cuyo valor es una función y a la que se llama a través de un objeto. Permite que una acción use los datos actuales del registro.
Escribe un método con this
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
counter.increment(); // 1
counter.increment(); // 2
La sintaxis abreviada increment() { ... } define una propiedad cuyo valor es una función ordinaria. En counter.increment(), el objeto receptor counter pasa a ser this. Cada llamada lee el contador almacenado, suma uno y devuelve el nuevo número.
Un count sin más selecciona una variable, no la propiedad. Si no hay una variable correspondiente, count += 1 lanza un ReferenceError. Usa this.count para acceder al campo del objeto receptor.
Lee una función o ejecútala
counter.increment lee un valor de tipo "function". Los paréntesis en counter.increment() la ejecutan y dan su valor de retorno. Al pasar una acción para usarla más adelante, el código que la recibe necesita la función, no el resultado de ejecutarla ahora.
Los métodos integrados también usan esta forma de llamada: Math.max(3, 7) devuelve 7 y "abc".toUpperCase() devuelve "ABC".
Reutiliza una acción
function describe() {
return this.name + " (" + this.year + ")";
}
const film = { name: "Up", year: 2009, describe };
const song = { name: "Hello", year: 2015, describe };
film.describe() devuelve "Up (2009)"; song.describe() devuelve "Hello (2015)". Usar this permite que la misma función lea cualquiera de los dos objetos receptores. Escribir film.name directamente la vincularía a la variable de la película.
Devuelve el objeto receptor para otra acción
const playlist = {
tracks: [],
add(title) { this.tracks.push(title); return this; },
count() { return this.tracks.length; }
};
playlist.add("Rain").add("Waves").count(); // 2
Cada llamada a add devuelve la lista de reproducción, lo que permite buscar el siguiente método en ese objeto. Devolver un número desde add rompería la cadena porque el siguiente add se buscaría en ese número.
La conversión ordinaria a JSON omite los métodos: al serializar { name: "Kit", hi() { return 1; } } solo se escribe name. El análisis no puede restaurar el código omitido. Los registros para guardar o intercambiar suelen contener datos ordinarios y usar funciones de procesamiento separadas.
Puntos clave
- Un método es una propiedad cuyo valor es una función y a la que se llama a través de un objeto.
- En
obj.method(), un método ordinario usaobjcomothis. - Una función como valor y el resultado de llamarla son valores distintos.
- Devolver
thispuede permitir que siga otra llamada a un método. - La conversión ordinaria a JSON omite las propiedades cuyo valor es una función.
2.2 Explica cómo obtiene this su valor
Para una función ordinaria, la llamada determina this. Almacenar una función en un objeto no la vincula permanentemente a ese objeto.
Sigue el objeto receptor en la llamada
const a = { n: "A", who() { return this.n; } };
const b = { n: "B" };
b.who = a.who;
a.who(); // "A"
b.who(); // "B"
Ambas propiedades contienen la misma función. El objeto receptor antes del punto es distinto, por lo que los resultados son distintos. La ubicación original de la función no determina qué objeto lee.
Para una llamada sin receptor, f(), el modo estricto proporciona undefined como this. Los módulos de JavaScript siempre se ejecutan en modo estricto; un script o una función también pueden comenzar con "use strict";. Una función ordinaria no estricta llamada sin receptor usa en su lugar el objeto global, globalThis. En un navegador, ese objeto global es window.
Reconoce el contexto circundante de una función flecha
Una función flecha no tiene un this propio. Conserva el this del código circundante donde se creó. Un literal de objeto no crea un nuevo contexto de this.
// At the top level of a module:
const user = {
name: "Ida",
hi: () => "Hi, " + this.name
};
Llamar a user.hi() lanza un TypeError: la función flecha capturó el this del nivel superior del módulo, que es undefined. Cambiar la llamada para que parezca una llamada a método no puede dar a la función flecha un objeto receptor nuevo. En el nivel superior de un script clásico, el this circundante es, en cambio, el objeto global.
Usa un método ordinario cuando la acción necesite el objeto desde el que se llama. Usa una función flecha dentro de ese método cuando una función de devolución de llamada necesite conservar el contexto del método:
const group = {
title: "Team",
members: ["Ana", "Ben"],
list() {
return this.members.map(m => this.title + ": " + m);
}
};
group.list(); // ["Team: Ana", "Team: Ben"]
list obtiene group de su llamada como método. La función flecha se crea dentro de ese método durante su ejecución y conserva el mismo this. Una función de devolución de llamada ordinaria en modo estricto, sin un objeto receptor proporcionado, recibiría undefined, por lo que this.title fallaría allí.
Sigue un orden de decisión
Cuando encuentres una llamada, identifica primero la función a la que se llama:
- Una función flecha conserva su
thiscircundante;call,applyybindno pueden sustituirlo. - Una función ordinaria vinculada conserva su
thisvinculado, incluso mediantecalloapply. - Una función ordinaria no vinculada a la que se llama con
calloapplyusa elthisproporcionado. - Una llamada ordinaria
obj.method()usaobj. - Una llamada ordinaria sin receptor usa
undefineden modo estricto o el objeto global en modo no estricto.
Las funciones de devolución de llamada pueden recibir un objeto receptor de quien las llama. Por ejemplo, un detector ordinario de eventos del DOM registrado con addEventListener recibe como this el elemento en el que está registrado. Revisa cómo el código receptor invoca una función de devolución de llamada antes de suponer que es una llamada sin receptor.
Puntos clave
- Una función ordinaria obtiene
thisde su llamada, por lo que prestar un método cambia su objeto receptor. - Una llamada sin receptor en modo estricto usa
undefinedcomothis. - Una función flecha conserva el
thiscircundante del lugar donde se creó. - Un objeto receptor vinculado tiene prioridad sobre un
calloapplyposterior. - Una función flecha dentro de un método ordinario puede conservar el
thisde ese método.
2.3 Conserva this al pasar métodos como funciones de devolución de llamada
Extraer un método de su objeto conserva la función, pero pierde la expresión de llamada original. Una función de devolución de llamada debe invocarse de forma que reciba el objeto que necesita.
Identifica un método desvinculado
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
const inc = counter.increment;
inc(); // TypeError in strict mode
inc() es una llamada sin receptor, por lo que this es undefined. Leer this.count falla antes de que pueda producirse un incremento. En código no estricto, una llamada sin receptor usa el objeto global y puede escribir un count global; no accede al contador.
El mismo problema aparece en las funciones de devolución de llamada de arrays. [1, 2].map(counter.increment) proporciona una función a map sin su objeto receptor original. Los valores del array que se pasan como argumentos no proporcionan this.
Envuelve la llamada al método
const results = [1, 2].map(() => counter.increment());
// results is [1, 2]; counter.count is 2
La función de devolución de llamada es una función flecha que realiza una llamada normal a counter.increment(). Esa llamada tiene un objeto receptor. La función envolvente ignora deliberadamente los valores que pasa map; cada invocación simplemente incrementa una vez. Esta forma resulta cómoda cuando solo se necesita la función de devolución de llamada en un lugar.
Vincula una función reutilizable
Partiendo de un contador nuevo en cero:
const boundInc = counter.increment.bind(counter);
const results = [1, 2].map(boundInc);
// results is [1, 2]; counter.count is 2
bind devuelve una función nueva; todavía no llama al método. La nueva función conserva counter como objeto receptor. Volver a vincularla a un objeto diferente no puede sustituir ese receptor. Cada llamada a bind crea una función distinta, así que guarda el resultado cuando el código deba reconocer exactamente la misma función de devolución de llamada más adelante.
La vinculación también puede fijar argumentos iniciales. function multiply(a, b) { return a * b; } seguido de const double = multiply.bind(null, 2); hace que double(21) devuelva 42. null ocupa la posición del objeto receptor porque esta función no usa this; 2 ocupa su primer parámetro ordinario.
Ejecuta una vez con call o apply
function describe(unit) {
return this.value + " " + unit;
}
describe.call({ value: 12 }, "kg"); // "12 kg"
describe.apply({ value: 12 }, ["kg"]); // "12 kg"
Ambas formas se ejecutan inmediatamente con el objeto receptor elegido. call proporciona los argumentos por separado; apply los proporciona en un array. El contexto de una función flecha queda fijado por su entorno, por lo que estos métodos no pueden sustituir su this.
Pasar counter.increment() como función de devolución de llamada ejecuta el método inmediatamente y pasa el número que devuelve. Esa no es la función que necesita map. En un registro de eventos como button.addEventListener("click", counter.increment()), el contador cambia inmediatamente y el detector numérico provoca un TypeError. Pasa una función como valor, una función envolvente de tipo flecha o una función vinculada almacenada.
Puntos clave
- Desvincular un método elimina su objeto receptor original.
- Una función envolvente de tipo flecha puede realizar más adelante la llamada necesaria al método.
bindcrea una función con un objeto receptor fijo y argumentos iniciales opcionales.callyapplyejecutan inmediatamente; sus formatos de argumentos son distintos.- Los argumentos que se usan como funciones de devolución de llamada deben ser funciones, no el resultado numérico de ejecutar un método.
3Extrae y combina datos con desestructuración, propagación y resto
La desestructuración da nombres a partes seleccionadas de un objeto o de una colección ordenada. La propagación construye valores a partir de partes existentes, mientras que el resto recopila las partes que sobran. Estas formas suelen aparecer juntas en funciones que reciben opciones o devuelven registros actualizados. Observar con atención su posición te permite predecir qué variables existen, qué valores predeterminados se aplican y si los datos anidados se comparten con el original.
3.1 Desestructura objetos
La desestructuración de objetos lee campos nombrados y los asigna a variables locales. Selecciona valores sin copiar todo el registro de origen.
Empareja y cambia nombres
const book = { title: "Dune", pages: 412 };
const { pages, title: bookTitle, rating: stars = 0 } = book;
El emparejamiento usa los nombres de las propiedades, no su orden. Esto declara pages con valor 412, bookTitle con "Dune" y stars con 0. No declara ninguna variable title ni rating: el nombre después de los dos puntos es el destino local.
Un campo ausente proporciona undefined. Un valor predeterminado sustituye solo a undefined y conserva null, cero, false y las cadenas vacías. Por tanto, const { a = 5 } = { a: null }; deja a con valor null.
Sigue los campos anidados
const data = {
location: { name: "Oslo" },
current: { tempC: -3, windKph: 18 }
};
const {
location: { name },
current: { tempC, windKph: wind }
} = data;
Las variables declaradas son name, tempC y wind, que contienen "Oslo", -3 y 18. Los nombres externos location y current seleccionan rutas; no se convierten también en variables.
La ausencia de un objeto externo hace que falle una lectura anidada. const { shipping: { date } } = {}; lanza un TypeError. Proporciona un valor predeterminado externo cuando ese campo pueda ser undefined:
const { shipping: { date } = {} } = {};
// date is undefined
Esto no sustituye shipping cuando su valor es null. Desestructurar directamente null o undefined también lanza un error, por lo que el origen debe poder usarse antes de comenzar la extracción.
Recibe opciones nombradas
function formatUser({ name, age = "unknown" }) {
return name + ", " + age;
}
formatUser({ name: "Mo" }) devuelve "Mo, unknown". Cambiar el orden de los campos en { age: 40, name: "Ines" } sigue devolviendo "Ines, 40". Llamar a formatUser sin argumentos falla porque no hay ningún objeto del que extraer valores. Un valor predeterminado para todo el parámetro permite esa llamada:
function greet({ name = "guest" } = {}) {
return "Hi, " + name;
}
greet(); // "Hi, guest"
El valor predeterminado externo maneja un argumento omitido; el interno maneja un nombre ausente. Pasar null sigue provocando un error. Para asignar valores a variables existentes, rodea con paréntesis una sentencia con un patrón de objeto: let x, y; ({ x, y } = { x: 4, y: 7 });. De lo contrario, las llaves iniciales se interpretan como un bloque de sentencias.
Puntos clave
- Los patrones de objeto emparejan propiedades por nombre.
- Los dos puntos cambian el nombre de la variable; no cambian la clave de origen.
- Los valores predeterminados sustituyen a
undefined, incluidas las propiedades ausentes, y conservannull. - Los patrones anidados necesitan un objeto utilizable en cada nivel.
- Un valor predeterminado para todo el parámetro y uno para una propiedad manejan valores ausentes distintos.
- Los paréntesis permiten que un patrón de objeto asigne valores a variables existentes.
3.2 Desestructura arrays y otros iterables
La desestructuración de arrays lee valores por posición de un iterable. Las comas controlan qué valores se seleccionan; los nombres de las variables no eligen las posiciones.
Selecciona u omite posiciones
const medals = ["gold", "silver", "bronze"];
const [first, second] = medals;
const [, , third] = medals;
Las variables reciben "gold", "silver" y "bronze". Las posiciones vacías consumen valores sin declarar variables. Un nombre situado más allá de los valores disponibles recibe undefined. Los valores predeterminados sustituyen solo a undefined:
const [p, q = 10] = [1]; // p is 1; q is 10
const [r = 10] = [null]; // r is null
Recopila los valores restantes
const [head, ...tail] = [1, 2, 3, 4];
// head is 1; tail is [2, 3, 4]
El elemento de resto final crea un array nuevo, vacío cuando no queda nada. Debe ir al final. Los valores de objeto dentro de ese array conservan su identidad; recopilarlos no los clona en profundidad.
Lee un par devuelto o intercambia variables
function minMax(nums) {
return [Math.min(...nums), Math.max(...nums)];
}
const [lo, hi] = minMax([4, 9, 1]);
// lo is 1; hi is 9
Quien llama sigue el orden acordado por la función que devuelve los valores. Para muchos campos de resultado, las propiedades de objeto nombradas evitan tener que recordar posiciones.
Con let x = 1, y = 2;, [x, y] = [y, x]; intercambia las variables. El array de la derecha se evalúa como [2, 1] antes de cualquiera de las asignaciones, lo que conserva ambos valores anteriores sin una variable temporal.
Extrae valores de otros iterables
También se pueden extraer valores de cadenas y Set: const [initial] = "Zoe"; da "Z". Los Set proporcionan valores en orden de inserción. Las entradas de Map son pares ordenados:
const distances = new Map([["park", 2], ["lake", 5]]);
for (const [place, distanceKm] of distances) {
console.log(place, distanceKm);
}
El bucle recibe un par y después el patrón separa su clave y su valor. Object.entries proporciona la misma estructura de pares.
Un objeto ordinario no es iterable, por lo que const [name] = { name: "Ana" }; lanza un TypeError. Usa llaves para seleccionar su campo nombrado: const { name } = { name: "Ana" };. Los corchetes requieren una secuencia de valores; las llaves seleccionan propiedades por nombre.
Puntos clave
- Los patrones de array emparejan posiciones y las posiciones vacías omiten valores.
- Una posición ausente se convierte en
undefinedsalvo que la sustituya un valor predeterminado. - Un elemento de resto final recopila los valores restantes en un array nuevo.
- Los patrones de array también funcionan con cadenas, Set y entradas de Map.
3.3 Copia, combina y recopila datos con propagación y resto
Los tres puntos, ..., tienen dos funciones relacionadas. La propagación expande datos existentes en un valor o una llamada. El resto recopila valores en una variable donde la declara un patrón o un parámetro.
Combina en orden de prioridad
const defaults = { lang: "en", units: "metric", alerts: true };
const user = { lang: "pt", alerts: false };
const options = { ...defaults, ...user };
// { lang: "pt", units: "metric", alerts: false }
La propagación de propiedades de objetos copia las propiedades propias y enumerables. Cuando una clave vuelve a aparecer, prevalece el valor posterior. Colocar user antes de defaults sobrescribiría la configuración del usuario. Propagar null o undefined en un objeto no añade nada.
Las copias mediante propagación son superficiales. Si cambia un registro anidado, copia también ese nivel:
const settings = { theme: "dark", font: { size: 14, family: "serif" } };
const next = {
...settings,
font: { ...settings.font, size: 18 }
};
La propagación externa conserva theme. La interna conserva family y sustituye size. settings.font.size sigue siendo 14 porque el registro anidado modificado es nuevo.
Sustituye un registro de una lista
const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map(t =>
t.id === 2 ? { ...t, done: true } : t
);
map crea un array nuevo. El elemento que coincide se convierte en un objeto nuevo, por lo que updated[1].done es true mientras que todos[1].done sigue siendo false. El primer elemento, que no cambia, se reutiliza: updated[0] === todos[0] es true. Las actualizaciones independientes no requieren copiar los registros que no cambian.
Expande valores de iterables
En un literal de array o una llamada a función, la propagación toma valores de un iterable. [...a, ...b] une sus valores en un array nuevo. Math.max(...[4, 9, 1]) pasa tres argumentos y devuelve 9. Un objeto ordinario no puede expandirse en un array: [...{ a: 1 }] lanza un TypeError. La propagación de propiedades de objetos y la de valores de iterables usan reglas distintas para determinar qué leen.
Recopila argumentos o propiedades restantes
function total(...nums) {
return nums.reduce((sum, n) => sum + n, 0);
}
total(2, 3, 5); // 10
total(); // 0
Un parámetro de resto recibe un array real, incluso cuando no recibe ningún valor. Debe ser el último parámetro y solo puede haber uno. El antiguo objeto arguments no es un array real. Las funciones flecha no tienen un arguments propio, aunque pueden leer el enlace de una función ordinaria que las contiene.
El resto de propiedades de un objeto recopila las propiedades propias y enumerables que aún no se han seleccionado:
const userRecord = { id: 8, name: "Rae", password: "x9!k" };
const { password, ...publicUser } = userRecord;
// publicUser is { id: 8, name: "Rae" }
Esto crea un registro nuevo y deja el origen sin cambios. La propiedad de resto debe ir al final. Fíjate en la posición para distinguir las funciones: los tres puntos en un literal o una llamada expanden hacia fuera; los tres puntos en una lista de parámetros o un destino de desestructuración recopilan hacia dentro.
Puntos clave
- Las propiedades posteriores prevalecen cuando se solapan propagaciones de objetos.
- Copia cada nivel anidado que deba cambiar de forma independiente.
- La propagación en arrays y llamadas necesita un iterable.
- El resto recopila argumentos, elementos o propiedades restantes y debe ir al final.
- Una actualización basada en map puede copiar un registro modificado y reutilizar los que no cambian.
- Los parámetros de resto son arrays reales; el antiguo objeto
argumentsno lo es.
4Almacena colecciones con Map y Set
Algunas colecciones necesitan claves que sean objetos o números y otras necesitan conservar cada valor una sola vez. Map y Set expresan esas necesidades directamente. Crearás entradas, comprobarás la pertenencia, seguirás el orden de inserción y convertirás colecciones en arrays u objetos cuando otra operación necesite esa estructura. La igualdad sigue siendo importante: dos registros con campos que coinciden pueden seguir siendo dos valores separados en cualquiera de las dos colecciones.
4.1 Almacena pares clave-valor en un Map
Un Map almacena asociaciones entre claves y valores. A diferencia de las claves de cadena de un objeto ordinario, una clave de Map puede ser un número, un objeto u otro valor sin convertirse en una cadena.
Crea y mantén entradas
const stock = new Map();
stock.set("apples", 12).set("pears", 7);
stock.get("apples"); // 12
stock.has("kiwis"); // false
stock.size; // 2
set añade una entrada o sustituye su valor y devuelve el Map para permitir el encadenamiento. get devuelve undefined para una clave ausente; usa has para distinguirla de una entrada que almacena undefined. delete(key) devuelve si eliminó una entrada y clear() vacía la colección.
La notación de corchetes usa una zona de almacenamiento distinta: stock["plums"] = 5; añade una propiedad ordinaria al objeto Map. No crea una entrada visible para get, has o size. Usa los métodos de Map para las entradas.
Conserva los tipos y las identidades de las claves
m.set(1, "number"); m.set("1", "text"); crea dos entradas. Las claves 1 y "1" de un objeto ordinario harían referencia a una sola propiedad. Las claves de Map se comparan como con ===, salvo que NaN coincide consigo mismo y los ceros con signo comparten una clave.
const person = { id: 1 };
const notes = new Map([[person, "ready"]]);
notes.get(person); // "ready"
notes.get({ id: 1 }); // undefined
La segunda búsqueda crea un objeto nuevo. Que los campos coincidan no lo convierte en la misma clave. Conserva y reutiliza la referencia al objeto original cuando uses un objeto como clave.
Recorre y convierte pares
for (const [name, count] of stock) {
console.log(name, count);
}
Un Map proporciona pares [key, value] en el orden de la primera inserción. Sustituir un valor no mueve su clave. keys(), values() y entries() devuelven iteradores que puedes recorrer o propagar en arrays. forEach pasa a su función de devolución de llamada primero el valor y después la clave.
new Map(Object.entries(obj)) convierte las entradas de un registro en un Map. Object.fromEntries(map) crea un objeto; úsalo cuando las claves sean cadenas, porque las claves de objeto no pueden conservar todos los tipos de clave de Map. [...map] crea un array de pares, útil para guardar las entradas de un Map como JSON.
Cuenta claves que cambian
const words = "the cat saw the dog and the bird".split(" ");
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
La primera aparición comienza en cero y después suma uno. Las apariciones posteriores leen y aumentan la cuenta almacenada. counts.get("the") es 3 y counts.size es 6: el tamaño cuenta palabras distintas, no las ocho apariciones.
Elige un objeto ordinario para un registro con campos conocidos, especialmente para datos compatibles con JSON. Elige un Map para claves que cambian, comprobaciones frecuentes del tamaño o claves cuyos tipos deban conservarse. El método más reciente Map.groupBy conserva los tipos de las claves de grupo:
const owner = { name: "Ari" };
const jobs = [{ owner, done: false }, { owner, done: true }];
const byOwner = Map.groupBy(jobs, job => job.owner);
byOwner.get(owner).length; // 2
En código más antiguo, recorre las tareas. Para cada propietario, usa has y set para crear una sola vez un array de grupo y después get(owner).push(job) para añadir el registro. Mantener el propietario como clave de objeto distingue a propietarios diferentes incluso cuando sus campos de nombre coinciden. Un WeakMap puede asociar metadatos a objetos sin mantener vivos objetos usados como claves que de otro modo serían inalcanzables. No permite la iteración ni tiene tamaño. Los WeakMap modernos también aceptan símbolos no registrados como claves.
Puntos clave
- Las claves de Map conservan sus tipos y comparan los objetos por identidad.
- Usa
set,get,hasydeletepara las entradas, no la notación de corchetes. sizecuenta las entradas y la iteración sigue el orden de inserción de las claves.- Los Map se convierten mediante pares clave-valor.
- Un WeakMap puede contener metadatos de objetos sin mantener vivos los objetos usados como claves.
Map.groupByconserva los tipos de las claves de grupo en una API de agrupación más reciente.
4.2 Conserva valores únicos en un Set
Un Set almacena valores únicos. Sus preguntas principales son si un valor está presente y cómo se solapan dos colecciones.
Añade y comprueba valores
const tags = new Set(["js", "css", "js"]);
tags.size; // 2
tags.add("html");
tags.has("css"); // true
Añadir un valor existente no cambia nada. add devuelve el Set para permitir el encadenamiento. delete(value) devuelve si se eliminó el valor, mientras que clear() elimina todos los valores. El constructor recibe un iterable: usa new Set([1, 2, 3]). new Set(1, 2, 3) lanza un TypeError porque su primera entrada no es iterable. Una cadena es iterable, por lo que new Set("hello") contiene "h", "e", "l" y "o".
Un Set no tiene posiciones indexadas. tags[0] es undefined. Recorre con for...of, llama a forEach o convierte a un array para operaciones como map y filter. La iteración sigue el orden de inserción; eliminar un valor y volver a añadirlo lo coloca al final.
Elimina duplicados sin ordenar
const unique = [...new Set([3, 1, 3, 2, 1])];
// [3, 1, 2]
El Set conserva la primera aparición de cada valor. La propagación coloca esos valores en un array. Array.from(set) realiza la misma conversión.
Los valores se comparan como con ===, salvo que NaN coincide consigo mismo; los ceros con signo cuentan como un solo valor. Los valores de objeto se comparan por identidad: new Set([{ id: 1 }, { id: 1 }]).size es 2. Para conservar un registro por ID, construye un Map con ese ID como clave y después lee sus valores. Los registros posteriores con el mismo ID sustituyen a los anteriores, porque set actualiza una entrada existente.
Para comprobar repetidamente la pertenencia en colecciones grandes, un Set evita la búsqueda uno por uno de includes en un array. Úsalo cuando la presencia importe más que la posición.
Compara dos colecciones
Los métodos más recientes de Set están disponibles en los principales navegadores desde 2024. Con a que contiene 1, 2, 3, 4 y b que contiene 3, 4, 5:
| Operación | Significado | Valores resultantes |
|---|---|---|
a.union(b) | En cualquiera de las colecciones | 1, 2, 3, 4, 5 |
a.intersection(b) | En ambas | 3, 4 |
a.difference(b) | En a pero no en b | 1, 2 |
a.symmetricDifference(b) | En exactamente una | 1, 2, 5 |
Estos métodos devuelven Set nuevos. isSubsetOf comprueba que todos los valores estén en la otra colección. isSupersetOf comprueba la inclusión inversa. isDisjointFrom comprueba que las colecciones no compartan valores. Los tres devuelven booleanos. Por ejemplo, new Set([3, 4]).isSubsetOf(a) es verdadero. La diferencia tiene una dirección: los valores en b pero no en a serían solo 5.
En un entorno más antiguo, una intersección puede escribirse como new Set([...a].filter(x => b.has(x))).
Una llamada ordinaria a JSON.stringify(set) produce "{}" y pierde los valores almacenados. Convierte a un array antes de escribir JSON y después usa new Set(parsedArray) al leerlo. Un WeakSet puede marcar objetos como procesados sin mantener vivos objetos que de otro modo serían inalcanzables. No se puede recorrer. Los WeakSet modernos también aceptan símbolos no registrados.
Puntos clave
- Un Set almacena cada valor distinto una sola vez y comprueba su presencia con
has. - Convierte un Set en un array para usar índices o métodos de array.
- Los valores de objeto siguen siendo distintos salvo que sus referencias coincidan.
- La unión, la intersección, la diferencia y la diferencia simétrica responden a preguntas distintas sobre pertenencia.
- La diferencia depende de qué Set va primero.
- Convierte los valores de Set en un array antes de escribir JSON.
- WeakSet puede marcar objetos sin mantenerlos vivos.
5Convierte datos a JSON y de JSON a valores
JSON transporta datos estructurados como texto. Convertir entre ese texto y valores activos de JavaScript solo es útil cuando sabes qué información sobrevive a la conversión. Reconocerás JSON válido, controlarás cómo se escriben los valores y manejarás entradas mal formadas al leerlas. Tras un análisis correcto también hay que comprobar la estructura antes de que el programa dependa de sus campos; un texto válido por sí solo no puede garantizar los datos esperados.
5.1 Lee y escribe en formato JSON
JSON es un formato de texto independiente del lenguaje para datos estructurados. Un objeto es un valor activo de JavaScript; JSON es texto que puede describir ese valor.
Reconoce los seis tipos de valor
JSON admite objetos, arrays, cadenas, números, booleanos y null. Cualquiera de ellos puede ser el valor de nivel superior. El texto 42 es JSON válido incluso sin llaves. JSON no tiene representación para funciones, undefined, fechas como tipo distinto, Map, Set, NaN ni Infinity.
{
"name": "Amara",
"age": 34,
"languages": ["en", "yo"],
"address": null,
"member": true
}
Las mismas ideas estructurales aparecen en los literales de JavaScript, pero la escritura permitida es más estricta. JSON se usa en configuraciones e intercambio de datos. El JSON intercambiado usa la codificación UTF-8 y el tipo de medio application/json; los archivos JSON usan la extensión .json.
Aplica las reglas de sintaxis
Cada clave de objeto debe ser una cadena entre comillas dobles. Las cadenas también requieren comillas dobles. Las comas separan propiedades o elementos de array, pero no puede haber una coma después del último. Los comentarios están prohibidos. Se permiten espacios en blanco entre valores y signos de puntuación.
| Texto | Por qué es inválido |
|---|---|
{name: "Amara"} | La clave no tiene comillas dobles. |
{'name': 'Amara'} | Las comillas simples no delimitan cadenas JSON. |
{"a": 1,} | La coma final no tiene una propiedad a continuación. |
{"a": undefined} | Undefined no es un valor JSON. |
Los números usan notación decimal. 1.5e3, -0.25 y 0 son válidos. 07, +1 y 0x1F son inválidos porque JSON prohíbe los ceros iniciales, el signo más inicial y la notación hexadecimal.
Escapa caracteres dentro de cadenas
Usa \" para una comilla doble, \\ para una barra invertida, \n para una nueva línea y \t para una tabulación dentro de una cadena JSON. No puede aparecer un salto de línea literal dentro de una cadena JSON. Deja que JSON.stringify genere secuencias de escape a partir de los valores reales de las cadenas para que las comillas internas no invaliden el resultado.
Una secuencia de escape Unicode consta de una barra invertida, la letra u y cuatro dígitos hexadecimales para una unidad de código UTF-16. Por ejemplo, \u00e9 representa é. Un carácter fuera de ese rango puede necesitar dos secuencias de escape de este tipo; también puede escribirse directamente en la cadena. Las comillas que rodean el texto JSON en el código fuente de JavaScript son una capa separada de las comillas dentro del propio JSON.
Conserva los identificadores y evita las claves duplicadas
Los números de JavaScript conservan todos los enteros del rango seguro desde -9 007 199 254 740 991 hasta 9 007 199 254 740 991. Fuera de ese rango, algunos enteros siguen siendo exactos y otros se redondean. Analizar '{"id":9007199254740993}' da un valor de id de 9 007 199 254 740 992. Almacena los identificadores largos como cadenas JSON cuando sus dígitos exactos sean importantes.
Las claves de objeto deberían ser únicas dentro de cada objeto JSON. JSON.parse de JavaScript conserva la última aparición cuando se repite una clave: analizar '{"a":1,"a":2}' produce { a: 2 }. No se pueden recuperar propiedades distintas a partir de ese nombre repetido.
Puntos clave
- JSON es texto con seis tipos de valor, incluidos los primitivos en el nivel superior.
- Las claves y cadenas necesitan comillas dobles; los comentarios y las comas finales son inválidos.
- Los números JSON excluyen la notación hexadecimal, los signos más iniciales y los ceros iniciales.
- Las secuencias de escape representan caracteres especiales dentro de las cadenas.
- Usa cadenas para identificadores largos cuyos dígitos exactos deban conservarse.
- Las claves de objeto repetidas no son seguras;
JSON.parseconserva el último valor.
5.2 Convierte valores en texto JSON con JSON.stringify
JSON.stringify convierte valores compatibles de JavaScript en texto JSON. Decide qué debe conservar el texto antes de convertir un registro con métodos o valores de colección.
Escribe texto compacto o con sangría
const person = { name: "Amara", age: 34, tags: ["admin"] };
const text = JSON.stringify(person);
// '{"name":"Amara","age":34,"tags":["admin"]}'
El resultado es una cadena, por lo que typeof text es "string". Las propiedades propias y enumerables con claves de cadena se escriben en el orden de Object.keys. JSON.stringify(person, null, 2) añade saltos de línea y dos espacios de sangría por nivel. El segundo argumento es null porque no se usa ningún sustituto de serialización. La sangría numérica está limitada a 10 espacios; una cadena usada para la sangría se limita a sus primeros 10 caracteres.
Predice los valores omitidos y modificados
const data = {
a: undefined,
b: () => 1,
c: NaN,
d: [undefined, Infinity]
};
JSON.stringify(data); // '{"c":null,"d":[null,null]}'
Se omite una propiedad de objeto que contiene undefined, una función o un símbolo. En un array, ese valor se convierte en null, con lo que se conserva la posición. NaN e Infinity se convierten en null en ambos casos. En el nivel superior, valores no admitidos como undefined o una función hacen que stringify devuelva undefined, no texto JSON.
Un Date escribe su cadena ISO en UTC mediante toJSON. Las entradas ordinarias de Map y Set no se escriben, por lo que cualquiera de las dos colecciones se convierte en {}. Convierte los valores de Set en un array y las entradas de Map en pares o en un objeto con claves de cadena antes de escribirlos.
Una referencia circular y un BigInt ordinario como 10n provocan un TypeError. Las referencias compartidas que no forman un ciclo pueden serializarse, pero JSON no conservará su identidad compartida.
Elige datos con un sustituto de serialización
const user = { name: "Rae", email: "rae@example.com", password: "x9!k", age: 31 };
JSON.stringify(user, ["name", "email"]);
// '{"name":"Rae","email":"rae@example.com"}'
Un array sustituto selecciona nombres de propiedades. Una función sustituta transforma los valores a medida que se visitan, comenzando por la entrada completa bajo la clave "":
JSON.stringify(user, (key, value) =>
key === "password" ? undefined : value
);
Devolver undefined omite una propiedad de objeto, convierte una posición de array en null o provoca un resultado general undefined cuando se devuelve para la raíz. Devuelve el valor sin cambios para los datos que quieras conservar.
El método toJSON() de un objeto puede elegir su representación. Para { celsius: 21, toJSON() { return { c: this.celsius }; } }, la serialización escribe '{"c":21}'.
No construyas JSON uniendo cadenas entrecomilladas por tu cuenta: las comillas internas o los saltos de línea pueden romper su sintaxis. Tampoco serialices texto ya serializado esperando una representación de objeto. Serializar '{"a":1}' codifica una cadena; analizar ese resultado una vez devuelve una cadena, no un objeto.
Puntos clave
JSON.stringifysuele devolver texto JSON; los valores no admitidos en el nivel superior pueden devolverundefined.- Las propiedades de objeto no admitidas desaparecen, mientras que los elementos de array no admitidos se convierten en
null. - Las fechas se convierten en cadenas; Map y Set necesitan una conversión explícita.
- Las estructuras circulares y los BigInt ordinarios lanzan
TypeError. - Los sustitutos de serialización y
toJSONcontrolan la representación escrita. - Volver a serializar texto JSON codifica una cadena, no el objeto que contiene.
5.3 Convierte texto JSON en valores con JSON.parse
JSON.parse lee texto JSON y devuelve el valor que describe. El análisis comprueba la sintaxis del texto; comprobar si el resultado se ajusta a tu programa es una tarea independiente.
Lee el valor y después inspecciona sus campos
const data = JSON.parse('{"city":"Lima","tempC":19.5}');
data.tempC + 1; // 20.5
Las comillas simples externas delimitan una cadena de JavaScript. Las comillas dobles dentro de ella pertenecen a JSON. El análisis crea un objeto ordinario con una propiedad numérica tempC. Un texto que describe un array produce un array; los textos JSON primitivos producen sus valores primitivos correspondientes.
Los datos que ya son un objeto no necesitan un paso de análisis. JSON.parse({ a: 1 }) convierte primero ese argumento en "[object Object]" y después lanza un SyntaxError. JSON.parse(undefined) también falla porque "undefined" no es texto JSON válido.
Maneja texto inválido
function safeParse(text, fallback) {
try {
return JSON.parse(text);
} catch (error) {
return fallback;
}
}
safeParse("{ok:true}", null); // null
Una entrada mal formada, incluidas una cadena vacía, cadenas JSON entre comillas simples, claves sin comillas y comas finales, lanza un SyntaxError. Capturar ese fallo da al programa una alternativa de respaldo deliberada en lugar de detenerlo. También es posible analizar correctamente null, así que decide cómo distinguirá quien llama una alternativa de respaldo de datos válidos cuando esa diferencia importe.
Restaura valores seleccionados con una función de transformación
Una fecha almacenada como texto vuelve como una cadena. Un array de pares clave-valor sigue siendo un array hasta que new Map(pairs) lo convierte en un Map. Las funciones omitidas al escribir no se pueden recuperar del texto restante.
const text = '{"title":"Dentist","due":"2026-03-01T09:00:00.000Z"}';
const event = JSON.parse(text, (key, value) =>
key === "due" ? new Date(value) : value
);
La función de transformación de valores analizados visita los valores internos antes que sus contenedores y termina con el resultado completo bajo la clave "". Devolver un valor sustituye el valor actual. Devolver undefined elimina esa propiedad; devolverlo para la raíz hace que todo el resultado del análisis sea undefined. Por tanto, olvidar return value para otras claves puede borrar los datos que querías conservar.
Comprueba la estructura y planifica una conversión de ida y vuelta
Un JSON válido aún puede tener tipos incorrectos. Analizar '{"temp":"19"}' deja una cadena, por lo que data.temp + 1 concatenaría hasta formar "191". Comprueba los campos y tipos obligatorios, como typeof data?.temp === "number", antes de calcular. Convierte con Number solo cuando el formato previsto permita una cadena numérica; el encadenamiento opcional y ?? pueden manejar campos que pueden faltar.
Para const settings = { theme: "dark", volume: 0.8, recent: ["a.txt"] };, la serialización produce 48 caracteres de texto JSON. Analizarlo restaura los mismos datos de los campos, pero loaded === settings es falso porque el análisis crea objetos nuevos. Un Date vuelve como una cadena, una propiedad de objeto con valor undefined desaparece y un Set sin convertir vuelve como {}. Convierte los valores especiales antes de escribir y restaura sus tipos previstos después de leer.
Puntos clave
JSON.parselee texto y lanzaSyntaxErrorpara JSON mal formado.- Un análisis correcto no comprueba los campos obligatorios ni sus tipos.
- Una función de transformación visita primero los valores hijos y debe devolver los valores que quieras conservar.
- Las conversiones de ida y vuelta mediante JSON crean objetos nuevos y conservan solo datos representables.
- Restaura explícitamente los tipos de colección y fecha después del análisis.
Ejemplos de Objetos y JSON en JavaScript
1Sigue un registro de envío
16 pasos
- 1IntroducciónConstruye un registro que puedas inspeccionar
Un envío combina un ID, un destino y registros de paquetes. Lo construirás, inspeccionarás sus campos y seguirás los datos compartidos y copiados. Dos nombres pueden contener una misma referencia al mismo registro, y una copia superficial sigue compartiendo los niveles anidados, de modo que una actualización puede alcanzar datos que querías mantener separados.
Los ejemplos del envío continúan de una diapositiva a otra salvo que un paso cree explícitamente un objeto separado.
- 2EjemploCrea el envío
const shipment = { id: "s12", destination: "Porto", delayMin: 0 };El literal crea tres propiedades. El retraso se mide en minutos e incluye un cero válido.
shipment.destinationlee"Porto". Const permite actualizar propiedades. - 3EjemploElige un campo durante la ejecución del programa
const field = "destination"; shipment[field] = "Braga"; shipment.checked = true;El acceso con corchetes evalúa field y actualiza la propiedad de destino. La asignación también añade checked porque no existía antes. El envío sigue teniendo la misma identidad; ninguna de las dos operaciones sustituye el objeto externo. Escribir
shipment.fieldcrearía en cambio una propiedad separada llamada literalmente"field". - 4DesafíoLee un nombre calculado
¿Qué lee ahora
shipment[field]y tiene el envío una propiedad propia field?---reveal---
Lee
"Braga". La variable field contiene la clave"destination", por lo que tanto la actualización como la lectura acceden a esa propiedad.Object.hasOwn(shipment, "field")es falso porque no se creó ninguna propiedad literal field. Una variable usada para elegir una propiedad no pasa por sí misma a formar parte del registro. - 5ExplicaciónComprueba el cero sin perderlo
shipment.delayMines cero, por lo que una condición que comprueba su valor en contexto booleano omite su cuerpo. La propiedad sigue existiendo.Object.hasOwn(shipment, "delayMin")devuelve verdadero. Usa una comprobación de propiedad propia para campos almacenados; el operador in también incluye propiedades heredadas. - 6EjemploLee las entradas
const pairs = Object.entries(shipment); const count = Object.keys(shipment).length;Ahora hay cuatro campos propios y enumerables con claves de cadena, incluido checked. Entries proporciona un par
[key, value]para cada uno. Puedes recorrerlos confor (const [key, value] of pairs)para inspeccionar ambas partes. Un bucle for...of directamente sobre el objeto ordinario shipment lanzaría un error porque ese objeto no es iterable. - 7DesafíoSepara la existencia del valor
Supón que se añade
shipment.note = undefined;. ¿Qué devuelvenshipment.noteyObject.hasOwn(shipment, "note")?---reveal---
Devuelven undefined y true. La asignación crea la propiedad aunque su valor sea undefined. Eliminar la propiedad cambiaría el resultado de la comprobación de existencia a false, mientras que una lectura posterior seguiría produciendo undefined. El valor por sí solo no puede distinguir estas dos situaciones.
- 8AnalogíaSigue dos rutas hacia un mismo registro
Una referencia funciona como una ruta hacia un registro: copiar la ruta proporciona otra forma de llegar al mismo destino. No construye un segundo registro.
const alias = shipment; alias.checked = false;shipment.checkedahora también es false. Ambos nombres de variable llegan a un mismo objeto, por lo quealias === shipmentes true. Las referencias coincidentes explican la actualización compartida; no se ejecutó ningún paso de sincronización entre dos copias. - 9EjemploAñade datos que compartirá una copia superficial
shipment.packages = [{ massG: 450 }, { massG: 700 }]; const shallow = { ...shipment }; shallow.destination = "Faro"; shallow.packages[0].massG = 500;El nuevo registro externo tiene su propio destino, por lo que
shipment.destinationsigue siendo Braga. Su valor packages es la misma referencia al array que antes. Seguir esa ruta compartida también cambia a 500 la masa del primer paquete del envío original. - 10EjemploCrea una copia profunda compatible
const deep = structuredClone(shipment); deep.packages[0].massG = 600;El primer paquete original permanece en 500 g porque la copia profunda tiene su propio array anidado y sus propios objetos de paquete. Este registro contiene solo datos compatibles. Si contuviera una propiedad cuyo valor fuera una función, structuredClone lanzaría DataCloneError en lugar de omitir silenciosamente ese método.
- 11DesafíoPredice el alcance de una congelación
Ejecuta estas sentencias. ¿Lanza un error la asignación anidada y cuál es después la segunda masa?
Object.freeze(shipment); shipment.packages[1].massG = 750;---reveal---
La asignación funciona y establece la masa en 750. Congelar shipment protege sus propiedades propias, pero no el array al que hace referencia ni sus registros. Reasignar
shipment.destinationen modo estricto lanzaría TypeError; esta asignación anidada llega a un objeto distinto que no está congelado. - 12EjemploCalcula el total actual
const totalG = shipment.packages.reduce( (sum, pack) => sum + pack.massG, 0 );Después de las actualizaciones anteriores, el envío original contiene masas de 500 y 750 g. Reduce empieza en cero, suma 500 y después 750, lo que produce 1250. El total se calcula a partir de los paquetes actuales. Si sus masas cambian más adelante, vuelve a ejecutar el cálculo; este número almacenado no se recalcula por sí solo.
- 13ConsejoProtege una ruta opcional
const contactName = shipment.contact?.name ?? "Unassigned";No hay una propiedad contact en el registro, por lo que el encadenamiento opcional da undefined y la alternativa de respaldo proporciona
"Unassigned". Esta ruta puede estar ausente. Mantén los campos obligatorios visibles para la validación en lugar de sustituir silenciosamente todos los errores por valores predeterminados. La alternativa para valores nulos o indefinidos también conserva un nombre vacío de forma intencionada, a diferencia de una alternativa con disyunción lógica. - 14DesafíoConserva un cero válido
¿Qué devuelven
shipment.delayMin ?? 10yshipment.delayMin || 10?---reveal---
El primero devuelve 0; el segundo devuelve 10. La coalescencia nula sustituye solo null o undefined, mientras que la disyunción lógica sustituye todos los valores falsos en contexto booleano. Este envío tiene registrado un retraso de cero minutos, por lo que tratarlo como ausente introduciría un retraso que los datos almacenados nunca indicaron.
- 15DesafíoCombina una copia con una actualización opcional
Se crea un registro nuevo con
const next = { ...shipment };y después se ejecutanext.packages[0].massG = 520;. ¿Qué ocurre con la primera masa de shipment y es next el mismo objeto externo?---reveal---
La masa original pasa a ser 520 porque el array anidado se comparte.
next === shipmentes false porque la propagación creó un objeto externo nuevo. Copiar el registro externo separa las asignaciones a sus propiedades propias, pero no hace independiente toda una ruta anidada. - 16RepasoElige la comprobación adecuada para la tarea
Elige una propiedad mediante una clave literal o calculada y distingue la existencia de su valor en contexto booleano. Antes de una actualización, sigue su ruta para determinar si llega a datos compartidos.
Copia los niveles anidados que deban ser independientes. Recalcula los totales derivados después de que cambien sus datos de entrada.
2Mantén una acción conectada a su objeto
12 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónSigue una acción a medida que se desplaza
- 2EjemploCrea y llama a una acción
- 3DesafíoLee la acción sin ejecutarla
- 4EjemploPresta la función ordinaria
- 5DesafíoDesvincula el método prestado
- 6Idea clavePon una función flecha dentro del método
- 7EjemploEnvuelve la llamada necesaria
- 8EjemploVincula una función de devolución de llamada una vez
- 9DesafíoElige entre ejecución inmediata o posterior
- 10ConsejoDa prioridad a una vinculación existente
- 11DesafíoSigue un método vinculado a través de otro objeto
- 12RepasoInterpreta la forma de llamada
3Extrae opciones y construye un registro actualizado
14 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónLee la sintaxis compacta en pasos pequeños
- 2EjemploSelecciona campos y cambia sus nombres
- 3EjemploEntra en un patrón anidado
- 4DesafíoLee un campo anidado con otro nombre
- 5DesafíoDistingue null de un valor ausente
- 6EjemploExtrae los valores de un rango devuelto
- 7EjemploRecopila los elementos restantes en su propio array
- 8DesafíoIntercambia valores antes de usarlos
- 9EjemploCombina valores predeterminados con sustituciones
- 10EjemploCopia el nivel anidado que cambia
- 11ConexiónElimina un campo del registro nuevo
- 12DesafíoElige una actualización independiente
- 13DesafíoRelaciona los patrones de entradas con la propagación
- 14RepasoIdentifica la función antes de seguir los valores
4Sigue las cuentas y la pertenencia de valores únicos
11 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónElige qué debe recordar la colección
- 2EjemploCrea cuentas con métodos de Map
- 3ConsejoMantén las entradas separadas de las propiedades
- 4DesafíoMantén distintos los tipos de clave
- 5EjemploReutiliza una clave de objeto
- 6EjemploRecopila etiquetas únicas
- 7DesafíoDecide si los registros son duplicados
- 8EjemploEncuentra las etiquetas compartidas y las que faltan
- 9Idea claveCambia la pregunta sobre pertenencia
- 10DesafíoRelaciona las cuentas con la pertenencia
- 11RepasoAjusta la estructura a la operación
5Escribe, lee y comprueba datos JSON
14 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónPlanifica ambas direcciones de la conversión
- 2ExplicaciónLee el texto como texto
- 3DesafíoCorrige un problema de sintaxis
- 4EjemploInspecciona la configuración activa
- 5EjemploConvierte la colección antes de escribir
- 6ConsejoDeja que el serializador escape las cadenas
- 7DesafíoPredice un elemento de array no admitido
- 8EjemploAnaliza y restaura las operaciones de pertenencia
- 9EjemploManeja el texto mal formado de forma deliberada
- 10DesafíoComprueba un valor válido pero inadecuado
- 11ExplicaciónRestaura un campo con una función de transformación
- 12DesafíoConserva la distinción entre claves de Map
- 13ConexiónMantén separados la clonación y el intercambio
- 14RepasoComprueba la sintaxis, la estructura y la representación
Ejercicios de Objetos y JSON en JavaScript
Set 1: Lee registros y sigue valores10 Preguntas de Práctica
Pregunta 1 de 10
¿Qué devuelve Object.hasOwn(record, "enabled")?
const record = { enabled: false };
Mostrar respuestaOcultar respuesta
Pregunta 2 de 10
¿Cuáles son los valores de record.region y record.key?
const key = "region";
const record = { [key]: "east" };
record[key] = "west";
Mostrar respuestaOcultar respuesta
"west". No se crea ninguna propiedad literal key, por lo que leer record.key devuelve undefined.Pregunta 3 de 10
¿Cuál es el valor de meter.value después de esta llamada?
const meter = {
value: 7,
add() { this.value += 3; }
};
meter.add();
Mostrar respuestaOcultar respuesta
Pregunta 4 de 10
¿Qué devuelve sensor[field]?
const sensor = { tempC: 16, field: "room" };
const field = "tempC";
Mostrar respuestaOcultar respuesta
"tempC", para seleccionar la propiedad que contiene 16. El acceso con punto en sensor.field leería, en cambio, la propiedad literal field y devolvería "room".Pregunta 5 de 10
¿Qué devuelve right.read()?
const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
Mostrar respuestaOcultar respuesta
right, por lo que this es right y el nombre devuelto es "Nia". La función se escribió primero en left, pero esa ubicación no vincula su objeto receptor. Devolver "Ivo" confundiría la ubicación de almacenamiento original con el objeto usado en la llamada actual.Pregunta 6 de 10
¿Cuáles son los valores de title y score después de la desestructuración?
const { name: title, score = 8 } = { name: "Reef", score: null };
Mostrar respuestaOcultar respuesta
name en la variable local title. Su valor predeterminado para score se usa solo para undefined, por lo que el null explícito permanece como null. Sustituir null por 8 aplicaría a la desestructuración la regla más amplia para valores nulos o indefinidos, cuando esta solo se activa con undefined.Pregunta 7 de 10
¿Qué valor recibe third?
const [, , third] = [4, 9, 12, 18];
Mostrar respuestaOcultar respuesta
Pregunta 8 de 10
¿Cuáles son los valores de m.size y m.get(2)?
const m = new Map([[2, "number"], ["2", "text"]]);
Mostrar respuestaOcultar respuesta
"2" ocupan dos entradas separadas. Buscar el 2 numérico devuelve "number". Un tamaño de 1 sería el resultado de tratar ambas claves como la misma cadena, que es como se comportan esos nombres como propiedades de un objeto ordinario.Pregunta 9 de 10
Mostrar respuestaOcultar respuesta
Pregunta 10 de 10
¿Qué texto se devuelve?
JSON.stringify({
note: undefined,
values: [undefined, NaN],
ok: false
});
Mostrar respuestaOcultar respuesta
note como null aplicaría incorrectamente la regla de los arrays a una propiedad de objeto; eliminar posiciones del array cambiaría su estructura.Set 2: Aplica patrones y conserva objetos receptores10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Qué devuelve trip.host?.name ?? "Guest"?
const trip = { host: null };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Cuáles son los valores finales de a.level y a === b?
const a = { level: 2 };
const b = a;
b.level = 5;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Cuáles son después los valores de source.mode y source.layout.width?
const source = { mode: "day", layout: { width: 40 } };
const copy = { ...source };
copy.mode = "night";
copy.layout.width = 60;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Qué función se puede pasar a map para que cada llamada actualice tally?
const tally = { n: 0, tick() { return ++this.n; } };
const result = ["x", "y"].map(/* callback */);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
Este código se ejecuta en el nivel superior de un módulo. ¿Qué ocurre al llamar a card.read()?
const card = { title: "Basin", read: () => this.title };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Después de next.panel.width = 90, ¿cuáles son los valores de next.mode y base.panel.width?
const base = { mode: "wide", panel: { width: 50 } };
const next = { mode: "small", ...base, panel: { ...base.panel } };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Qué valor recibe size?
const { size = 6 } = {};
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
¿Qué array produce esta expresión?
[...new Set(["red", "blue", "red", "green", "blue"])];
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
¿Cuál es el valor final de loaded?
const loaded = JSON.parse('{"count":4,"tag":"a"}', (key, value) => {
if (key === "count") return value * 2;
});
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
¿Qué ocurre cuando se analiza este texto?
JSON.parse('{"mode":"fast","mode":"slow"}');
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 3: Transforma colecciones y recupera datos10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Qué objeto crea la expresión?
Object.fromEntries(
Object.entries({ north: 3, south: 5 })
.map(([key, value]) => [key, value + 2])
);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Qué devuelve options.limit ?? 12?
const options = { limit: 0 };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Qué debe devolver add para que basket.add("pear").add("fig") use la misma cesta dos veces?
const basket = {
items: [],
add(item) { this.items.push(item); /* return here */ }
};
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Qué array se devuelve en este módulo?
function scale(n) { return this.factor * n; }
const twice = scale.bind({ factor: 2 });
const obj = { factor: 9, twice };
[obj.twice(3), twice.call({ factor: 5 }, 4)];
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
¿Qué se devuelve?
function combine(first, ...others) {
return [first, others.length];
}
combine(...[7, 3, 8, 2]);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
¿Cuáles son los valores de items[0].done, next[1] === items[1] y next === items?
const items = [{ id: 4, done: false }, { id: 9, done: false }];
const next = items.map(item =>
item.id === 4 ? { ...item, done: true } : item
);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Por qué lookup.get({ code: 8 }) es undefined?
const key = { code: 8 };
const lookup = new Map([[key, "ready"]]);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
¿Cuáles son los tamaños de a.difference(b) y a.symmetricDifference(b)?
const a = new Set([2, 4, 6]);
const b = new Set([4, 8]);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
¿Qué texto produce esto?
JSON.stringify({ label: "Arc", count: 3 }, ["label"]);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
Este módulo se ejecuta sin una función de transformación de valores analizados. ¿Cuáles son los valores de typeof loaded.due y loaded === original?
const original = { due: new Date("2026-07-12T00:00:00.000Z") };
const loaded = JSON.parse(JSON.stringify(original));
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 4: Analiza actualizaciones y llamadas10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Cuál es el valor de typeof box.open?
const box = { open() { return "opened"; } };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Cuáles son los valores finales de base.inner.n, clone.inner.n y copy.inner.n?
const base = { inner: { n: 2 } };
const copy = { ...base };
const clone = structuredClone(base);
Object.freeze(base);
copy.inner.n = 7;
clone.inner.n = 9;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Qué array devuelve Object.keys(data)?
const data = { z: 1, "10": 2, "02": 3, "2": 4, a: 5 };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Cuál es el valor de totalG y cambiar heavy.massG también cambia load.items[1].massG?
const load = { items: [
{ massG: 120, qty: 2 },
{ massG: 300, qty: 1 }
] };
const heavy = load.items.find(x => x.massG > 200);
const totalG = load.items.reduce((s, x) => s + x.massG * x.qty, 0);
heavy.massG = 350;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
¿Qué devuelve b.labels() en este módulo?
const a = {
prefix: "A",
names: ["oak"],
labels() { return this.names.map(n => this.prefix + n); }
};
const b = { prefix: "B", names: ["elm"], labels: a.labels };
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
¿Qué ocurre cuando se llama por separado a read() y a read({ prefs: null })?
function read({ prefs: { theme = "light" } = {} } = {}) {
return theme;
}
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Cuál es el valor de tail?
const [head, ...tail] = [6, 8, 11];
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
¿Cuáles son los valores de m.size y [...m.keys()]?
const m = new Map([["p", 1], ["q", 2]]);
m.set("p", 4);
m["r"] = 5;
m.delete("q");
m.set("q", 6);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
JSON.parse('{"depthM":+7}')?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
¿Cuáles son los valores de result.count y result.total?
const result = JSON.parse('{"count":"6","total":12}',
(key, value) => key === "count" ? Number(value) : value
);
result.total += result.count;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 5: Combina elecciones de datos y reglas de conversión10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
¿Cuál es el valor de Object.hasOwn(record, "old") después de estas sentencias?
const record = { old: undefined };
delete record.old;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
¿Cuáles son los valores de a === b, a.left === a.right y b.left === b.right?
const shared = { n: 1 };
const a = { left: shared, right: shared };
const b = JSON.parse(JSON.stringify(a));
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
¿Qué devuelve saved()?
const maker = {
n: 5,
make() { return () => this.n; }
};
const other = { n: 8, make: maker.make };
const saved = other.make().bind({ n: 12 });
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
¿Qué devuelve fixed.apply({ offset: 30 }, [4])?
function add(a, b) { return this.offset + a + b; }
const fixed = add.bind({ offset: 2 }, 7);
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
¿Cuáles son los valores de a, b y rest?
let a = 3, b = 8;
[a, b] = [b, a];
const [, ...rest] = [a, b, 13];
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
Después de publicCopy.profile.name = "New", ¿cuál es el valor de source.profile.name y sigue source teniendo secret como propiedad propia?
const source = { secret: "s", profile: { name: "Old" } };
const { secret, ...publicCopy } = source;
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
¿Cuál es el valor final de counts.get("moss")?
const counts = new Map();
for (const word of ["moss", "fern", "moss", "moss"]) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
¿Cuáles son los valores de records.size y ids.size?
const x = { id: 7 };
const records = new Set([x, x, { id: 7 }]);
const ids = new Set([...records].map(r => r.id));
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
¿Cuál es el valor de typeof JSON.parse(text)?
const text = JSON.stringify('{"x":3}');
Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
"3" con los valores "n" y "s". ¿Qué par de conversiones las conserva mediante JSON?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
¿Te atascas con una pregunta tuya? Ayuda con Tareas
Términos Clave
A
Actualización inmutable
Aplicación parcial
multiply.bind(null, 4) crea una función que multiplica su siguiente argumento por cuatro.Argumento de sangría
C
Cadena de caracteres en JSON
Clave de índice de array
"3" se ordena antes que "12" en Object.keys; "03" permanece entre las claves de cadena ordinarias.Coalescencia nula
settings.volume ?? 1 conserva un volumen explícito de cero, mientras que settings.volume || 1 lo sustituye.Comprobación de la estructura de datos
Conjunto (Set)
"ready" dos veces conserva un valor, mientras que añadir dos registros separados con datos coincidentes conserva ambos.Conjunto de referencias débiles (WeakSet)
Conversión de ida y vuelta
Copia profunda
structuredClone, editar un campo anidado copiado deja el campo original sin cambios.Copia superficial
D
Datos anidados
report.readings[0].tempC lee una lista, su primer registro y después un campo de temperatura.Desestructuración de arrays
const [low, high] = bounds; depende de que bounds coloque el valor menor antes que el mayor.Desestructuración de objetos
const { city, tempC } = reading; crea dos variables locales a partir de un registro meteorológico.Diferencia
active.difference(blocked) conserva los valores activos que no aparecen en el Set blocked.Diferencia simétrica
E
Elemento de resto en la desestructuración de arrays
const [leader, ...others] = names; separa el primer nombre de un array con los nombres restantes.Encadenamiento de métodos
list.add("a").add("b") funciona cuando la primera llamada devuelve un objeto con el siguiente método add.Encadenamiento opcional
record.owner?.name permite que falte owner sin intentar leer un nombre de undefined.Entero seguro
Entrada de Map
stock.set("tea", 4) cambia una entrada; stock["tea"] = 4 cambia una propiedad ordinaria.Error de sintaxis (SyntaxError)
JSON.parse.Existencia de una propiedad
count: 0 sigue teniendo una propiedad count; comprobar ese valor como condición no permite detectarla.F
Función de transformación de valores analizados (reviver)
JSON.parse que transforma valores después de sus valores hijos y usa sus valores de retorno para sustituirlos o eliminarlos.Función envolvente de tipo flecha
() => counter.tick() a map hace que cada función de devolución de llamada invoque tick a través del objeto counter.Función structuredClone
I
Identidad del objeto
id: 9 se comparan como distintos con === pese a tener los mismos datos.Intersección
Iterable
J
JSON
{"ready":true} describe un registro, mientras que true por sí solo también es un texto JSON completo y válido.L
Literal de objeto
const reading = { tempC: 22 }; crea un registro que contiene una medición de temperatura.Llamada sin receptor en modo estricto
f y llamar a f() en un módulo puede fallar cuando intenta leer this.name.M
Map
"5" siguen siendo entradas distintas cuando se almacenan en el mismo Map.Mapa de referencias débiles (WeakMap)
Método
tracker.advance() ejecuta la acción del rastreador, mientras que leer tracker.advance devuelve una función.Método apply
format.apply(reading, ["m", 2]) proporciona el mismo objeto receptor y los mismos valores que format.call(reading, "m", 2).Método bind
const next = meter.step.bind(meter); crea una función de devolución de llamada que conserva meter como objeto receptor.Método call
format.call(reading, "m", 2) proporciona a format el objeto receptor reading y dos argumentos separados.Método desvinculado
const read = sensor.read; conserva la función, pero read() no proporciona sensor como objeto receptor.Método JSON.parse
JSON.parse lee texto JSON y devuelve el valor de JavaScript que representa; lanza un SyntaxError cuando el texto está mal formado.Método JSON.stringify
JSON.stringify serializa valores de JavaScript compatibles en texto JSON y, opcionalmente, selecciona datos y añade sangría para facilitar la lectura.JSON.stringify(settings, null, 2) escribe una forma más legible sin cambiar la configuración representada.Método Map.groupBy
Map.groupBy es un método más reciente que agrupa elementos de un iterable en arrays dentro de un Map y conserva el tipo y la identidad de las claves de grupo.Método Object.freeze
Object.freeze impide añadir, eliminar y modificar las propiedades propias de un objeto, pero no congela los objetos anidados.Método Object.fromEntries
Object.fromEntries crea un objeto a partir de pares clave-valor, lo que resulta útil después de transformar entradas o un Map compatible.Método Object.groupBy
Object.groupBy es un método más reciente que agrupa elementos de un iterable en arrays bajo claves seleccionadas por una función de devolución de llamada, dentro de un objeto sin prototipo.Método prestado
b.read = a.read permite que b.read() use los datos de b cuando la función lee mediante this.Método toJSON
N
Nombre de propiedad calculado
const code = "es";, { [code]: "Hola" } crea una propiedad llamada "es".Notación de corchetes
const field = "heightM";, person[field] selecciona la medición de altura de la persona.Notación de punto
profile.name siempre selecciona la propiedad llamada "name", aunque exista una variable llamada name.O
Objeto de opciones
{ color, size } permite indicar qué significa cada ajuste sin depender del orden de las posiciones.Objeto receptor
account.describe(), account es el objeto receptor que el método usa para leer sus campos.Orden de inserción
P
Palabra clave this
Par clave-valor
Object.entries({ lake: 5 }) produce [["lake", 5]], listo para un bucle sobre claves y valores.Parámetro de resto
function total(...values) puede usar reduce con values incluso cuando la llamada no proporciona argumentos.Patrón anidado
const { owner: { name } } = item; necesita un objeto owner y declara solo name.Patrón de cambio de nombre
const { title: label } = page; crea label sin declarar una variable llamada title.Posición omitida
const [, second] = colors; omite el primer color y nombra solo el siguiente valor proporcionado.Propagación de propiedades de objetos
{ ...base, active: true } copia base y después proporciona el valor final de active.Propagación de valores de iterables
Math.max(...measurements) proporciona cada elemento del array como argumento separado a la función.Propiedad
active de { active: false } existe aunque su valor sea un booleano falso.Propiedad abreviada
city, el literal { city } crea el mismo campo que { city: city }.Propiedad globalThis
Propiedad propia
Object.hasOwn({}, "toString") es falso aunque "toString" in {} es verdadero.Prueba de pertenencia
map.has(key) puede encontrar una entrada existente incluso cuando map.get(key) devuelve undefined.R
Referencia
const backup = record; proporciona otra forma de acceder a record sin copiar sus campos.Referencia circular
record.self = record hace que una llamada ordinaria a JSON.stringify lance un TypeError para ese registro.Resto de propiedades de un objeto
const { password, ...publicRecord } = user; deja user intacto y excluye password de la copia.S
Secuencia de escape
Serialización
Sintaxis abreviada de métodos
reset() { this.n = 0; } define una acción sin dos puntos separados ni la palabra clave function.Subconjunto
Sustituto de serialización (replacer)
T
this léxico
U
Unión
V
Valor derivado
Valor predeterminado en la desestructuración
const { count = 2 } = { count: null };, el null explícito se conserva pese al valor predeterminado.Sobre esta unidad
Crea tus propios Materiales de Estudio
Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.