Objetos y JSON en JavaScript: propiedades, métodos y this

Aprende a modelar datos reales con objetos de JavaScript: crea y modifica propiedades, recórrelas y descubre por qué copiar una variable no copia el objeto al que hace referencia. Da comportamiento a los objetos con métodos y determina a qué se refiere la palabra clave this en cada tipo de llamada. Extrae y combina datos con desestructuración, propagación y resto, almacena colecciones en Map y Set, y convierte datos a texto JSON y de texto JSON a valores con JSON.stringify y JSON.parse.

PrincipianteUnidad 4 de 9 del curso Curso de Programación en JavaScript

Lo que aprenderás

  1. 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 propiedades
      Escribe 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 objeto
      Comprueba 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ón
      Explica por qué los objetos se comparten por referencia, compara objetos correctamente y crea copias superficiales y profundas.
    • Trabaja con datos anidados
      Lee 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.
  2. 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 objeto
      Define 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 valor
      Determina 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 llamada
      Reconoce cuándo un método pierde su objeto y corrígelo con una función envolvente de tipo flecha, bind, call o apply.
  3. Extrae valores de objetos y arrays con desestructuración, y copia, combina y recopila valores con la sintaxis de propagación y resto.
    • Desestructura objetos
      Extrae propiedades de objetos en variables, con cambio de nombre, valores predeterminados, patrones anidados y parámetros de función desestructurados.
    • Desestructura arrays y otros iterables
      Extrae 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 resto
      Usa 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.
  4. 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 Map
      Crea 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 Set
      Crea y actualiza un Set, elimina duplicados de arrays y compara colecciones mediante operaciones de conjuntos.
  5. 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 JSON
      Reconoce 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.stringify
      Convierte 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.parse
      Analiza 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.

Guía de estudio de Objetos y JSON en JavaScript

5 capítulos

1

Modela 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; delete la elimina.
  • const fija 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ónResultado
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.hasOwn comprueba las propiedades propias; in también comprueba las heredadas.
  • Object.entries proporciona pares clave-valor para bucles y transformaciones.
  • Object.fromEntries reconstruye 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.freeze bloquea los cambios en propiedades propias, pero es superficial.
  • structuredClone copia 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.
  • find devuelve 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.groupBy agrupa registros en arrays bajo claves.
  • Los nombres de campos, tipos y unidades coherentes facilitan el procesamiento de los registros.
2

Da 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 usa obj como this.
  • Una función como valor y el resultado de llamarla son valores distintos.
  • Devolver this puede 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:

  1. Una función flecha conserva su this circundante; call, apply y bind no pueden sustituirlo.
  2. Una función ordinaria vinculada conserva su this vinculado, incluso mediante call o apply.
  3. Una función ordinaria no vinculada a la que se llama con call o apply usa el this proporcionado.
  4. Una llamada ordinaria obj.method() usa obj.
  5. Una llamada ordinaria sin receptor usa undefined en 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 this de su llamada, por lo que prestar un método cambia su objeto receptor.
  • Una llamada sin receptor en modo estricto usa undefined como this.
  • Una función flecha conserva el this circundante del lugar donde se creó.
  • Un objeto receptor vinculado tiene prioridad sobre un call o apply posterior.
  • Una función flecha dentro de un método ordinario puede conservar el this de 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.
  • bind crea una función con un objeto receptor fijo y argumentos iniciales opcionales.
  • call y apply ejecutan 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.
3

Extrae 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 conservan null.
  • 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 undefined salvo 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 arguments no lo es.
4

Almacena 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, has y delete para las entradas, no la notación de corchetes.
  • size cuenta 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.groupBy conserva 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ónSignificadoValores resultantes
a.union(b)En cualquiera de las colecciones1, 2, 3, 4, 5
a.intersection(b)En ambas3, 4
a.difference(b)En a pero no en b1, 2
a.symmetricDifference(b)En exactamente una1, 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.
5

Convierte 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.

TextoPor 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.parse conserva 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.stringify suele devolver texto JSON; los valores no admitidos en el nivel superior pueden devolver undefined.
  • 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 toJSON controlan 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.parse lee texto y lanza SyntaxError para 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

5 Lecciones Interactivas

1

Sigue un registro de envío

16 pasos
Crea, inspecciona y copia un registro anidado mientras sigues qué valores se comparten.
  1. 1
    Introducció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.

  2. 2
    EjemploCrea 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.destination lee "Porto". Const permite actualizar propiedades.

  3. 3
    EjemploElige 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.field crearía en cambio una propiedad separada llamada literalmente "field".

  4. 4
    Desafí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.

  5. 5
    ExplicaciónComprueba el cero sin perderlo

    shipment.delayMin es 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.

  6. 6
    EjemploLee 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 con for (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.

  7. 7
    DesafíoSepara la existencia del valor

    Supón que se añade shipment.note = undefined;. ¿Qué devuelven shipment.note y Object.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.

  8. 8
    Analogí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.checked ahora también es false. Ambos nombres de variable llegan a un mismo objeto, por lo que alias === shipment es true. Las referencias coincidentes explican la actualización compartida; no se ejecutó ningún paso de sincronización entre dos copias.

  9. 9
    EjemploAñ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.destination sigue 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.

  10. 10
    EjemploCrea 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.

  11. 11
    Desafí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.destination en modo estricto lanzaría TypeError; esta asignación anidada llega a un objeto distinto que no está congelado.

  12. 12
    EjemploCalcula 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.

  13. 13
    ConsejoProtege 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.

  14. 14
    DesafíoConserva un cero válido

    ¿Qué devuelven shipment.delayMin ?? 10 y shipment.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.

  15. 15
    DesafíoCombina una copia con una actualización opcional

    Se crea un registro nuevo con const next = { ...shipment }; y después se ejecuta next.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 === shipment es 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.

  16. 16
    RepasoElige 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.

2

Mantén una acción conectada a su objeto

12 pasos
Sigue las llamadas a métodos, el contexto capturado y las funciones de devolución de llamada con un pequeño contador.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónSigue una acción a medida que se desplaza
  2. 2
    EjemploCrea y llama a una acción
  3. 3
    DesafíoLee la acción sin ejecutarla
  4. 4
    EjemploPresta la función ordinaria
  5. 5
    DesafíoDesvincula el método prestado
  6. 6
    Idea clavePon una función flecha dentro del método
  7. 7
    EjemploEnvuelve la llamada necesaria
  8. 8
    EjemploVincula una función de devolución de llamada una vez
  9. 9
    DesafíoElige entre ejecución inmediata o posterior
  10. 10
    ConsejoDa prioridad a una vinculación existente
  11. 11
    DesafíoSigue un método vinculado a través de otro objeto
  12. 12
    RepasoInterpreta la forma de llamada
3

Extrae opciones y construye un registro actualizado

14 pasos
Lee los patrones desde fuera hacia dentro y después copia solo los niveles que deban cambiar.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónLee la sintaxis compacta en pasos pequeños
  2. 2
    EjemploSelecciona campos y cambia sus nombres
  3. 3
    EjemploEntra en un patrón anidado
  4. 4
    DesafíoLee un campo anidado con otro nombre
  5. 5
    DesafíoDistingue null de un valor ausente
  6. 6
    EjemploExtrae los valores de un rango devuelto
  7. 7
    EjemploRecopila los elementos restantes en su propio array
  8. 8
    DesafíoIntercambia valores antes de usarlos
  9. 9
    EjemploCombina valores predeterminados con sustituciones
  10. 10
    EjemploCopia el nivel anidado que cambia
  11. 11
    ConexiónElimina un campo del registro nuevo
  12. 12
    DesafíoElige una actualización independiente
  13. 13
    DesafíoRelaciona los patrones de entradas con la propagación
  14. 14
    RepasoIdentifica la función antes de seguir los valores
4

Sigue las cuentas y la pertenencia de valores únicos

11 pasos
Usa Map para valores con claves que cambian y Set para la pertenencia; después compara colecciones.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónElige qué debe recordar la colección
  2. 2
    EjemploCrea cuentas con métodos de Map
  3. 3
    ConsejoMantén las entradas separadas de las propiedades
  4. 4
    DesafíoMantén distintos los tipos de clave
  5. 5
    EjemploReutiliza una clave de objeto
  6. 6
    EjemploRecopila etiquetas únicas
  7. 7
    DesafíoDecide si los registros son duplicados
  8. 8
    EjemploEncuentra las etiquetas compartidas y las que faltan
  9. 9
    Idea claveCambia la pregunta sobre pertenencia
  10. 10
    DesafíoRelaciona las cuentas con la pertenencia
  11. 11
    RepasoAjusta la estructura a la operación
5

Escribe, lee y comprueba datos JSON

14 pasos
Planifica una representación compatible con JSON, maneja texto inválido y restaura los tipos previstos.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónPlanifica ambas direcciones de la conversión
  2. 2
    ExplicaciónLee el texto como texto
  3. 3
    DesafíoCorrige un problema de sintaxis
  4. 4
    EjemploInspecciona la configuración activa
  5. 5
    EjemploConvierte la colección antes de escribir
  6. 6
    ConsejoDeja que el serializador escape las cadenas
  7. 7
    DesafíoPredice un elemento de array no admitido
  8. 8
    EjemploAnaliza y restaura las operaciones de pertenencia
  9. 9
    EjemploManeja el texto mal formado de forma deliberada
  10. 10
    DesafíoComprueba un valor válido pero inadecuado
  11. 11
    ExplicaciónRestaura un campo con una función de transformación
  12. 12
    DesafíoConserva la distinción entre claves de Map
  13. 13
    ConexiónMantén separados la clonación y el intercambio
  14. 14
    RepasoComprueba la sintaxis, la estructura y la representación

Ejercicios de Objetos y JSON en JavaScript

50 Preguntas de Práctica en 5 sets

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 };
  1. false
  2. undefined
  3. null
  4. true
Mostrar respuestaOcultar respuesta
Respuesta: D
El registro tiene enabled como propiedad propia, por lo que la comprobación es verdadera. Su valor almacenado false no superaría una comprobación en contexto booleano, pero ese valor no hace que la propiedad esté ausente.

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";
  1. "west" y undefined
  2. "east" y "west"
  3. undefined y "west"
  4. "west" y "east"
Mostrar respuestaOcultar respuesta
Respuesta: A
La clave calculada crea region y la asignación con corchetes la actualiza a "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();
  1. 7
  2. 3
  3. 10
  4. undefined
Mostrar respuestaOcultar respuesta
Respuesta: C
La llamada al método convierte meter en el objeto receptor y cambia value de 7 a 10. Que un método sin return devuelva undefined no deshace la actualización de su propiedad.

Pregunta 4 de 10

¿Qué devuelve sensor[field]?

const sensor = { tempC: 16, field: "room" };
const field = "tempC";
  1. "room"
  2. 16
  3. "tempC"
  4. undefined
Mostrar respuestaOcultar respuesta
Respuesta: B
El acceso con corchetes usa el valor de field, "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 };
  1. "Ivo"
  2. "Nia"
  3. undefined
  4. Un TypeError
Mostrar respuestaOcultar respuesta
Respuesta: B
La función ordinaria se llama a través de 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 };
  1. "Reef" y null
  2. "Reef" y 8
  3. undefined y 8
  4. undefined y null
Mostrar respuestaOcultar respuesta
Respuesta: A
El patrón lee la propiedad 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];
  1. 4
  2. 9
  3. 12
  4. 18
Mostrar respuestaOcultar respuesta
Respuesta: C
Las dos posiciones vacías omiten 4 y 9, por lo que 12 queda para third. Seleccionar 9 supondría omitir solo una posición; el nombre de la variable no selecciona por sí mismo un índice.

Pregunta 8 de 10

¿Cuáles son los valores de m.size y m.get(2)?

const m = new Map([[2, "number"], ["2", "text"]]);
  1. 1 y "text"
  2. 2 y "text"
  3. 1 y "number"
  4. 2 y "number"
Mostrar respuestaOcultar respuesta
Respuesta: D
Un Map conserva los tipos de clave, por lo que el 2 numérico y la cadena "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

Un archivo de datos debe conservar los dígitos exactos del ID 9 007 199 254 740 997 y poder analizarse como JSON. ¿Qué texto de registro cumple ambas condiciones?
  1. {"id":9007199254740997,"active":true}
  2. {id:"9007199254740997",active:true}
  3. {"id":"9007199254740997","active":true}
  4. {"id":'9007199254740997',"active":true}
Mostrar respuestaOcultar respuesta
Respuesta: C
Las claves entre comillas dobles y true en minúsculas hacen que el registro sea JSON válido, y una cadena conserva cada dígito del ID. El entero grande sin comillas se redondea durante el análisis en JavaScript, aunque su sintaxis sea válida. Las claves sin comillas o las comillas simples alrededor del ID no superan la comprobación de sintaxis de JSON.

Pregunta 10 de 10

¿Qué texto se devuelve?

JSON.stringify({
  note: undefined,
  values: [undefined, NaN],
  ok: false
});
  1. '{"values":[null,null],"ok":false}'
  2. '{"note":null,"values":[null,null],"ok":false}'
  3. '{"values":[],"ok":false}'
  4. '{"values":[null,null]}'
Mostrar respuestaOcultar respuesta
Respuesta: A
La propiedad de objeto con valor undefined se omite, mientras que undefined en un array se convierte en null. NaN también se convierte en null y el booleano válido false se conserva. Mantener 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 };
  1. null
  2. undefined
  3. "Guest"
  4. Un TypeError
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;
  1. 5 y true
  2. 2 y false
  3. 5 y false
  4. 2 y true
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;
  1. "night" y 60
  2. "day" y 40
  3. "night" y 40
  4. "day" y 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 */);
  1. tally.tick
  2. () => tally.tick()
  3. tally.tick()
  4. () => tally.tick
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 };
  1. Lanza un TypeError.
  2. Devuelve "Basin".
  3. Devuelve undefined.
  4. Lanza un ReferenceError.
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 } };
  1. "small" y 50
  2. "wide" y 90
  3. "small" y 90
  4. "wide" y 50
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

¿Qué valor recibe size?

const { size = 6 } = {};
  1. undefined
  2. 6
  3. null
  4. 0
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"])];
  1. ["blue", "green", "red"]
  2. ["red", "green", "blue"]
  3. ["red", "blue", "green"]
  4. ["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;
});
  1. undefined
  2. { count: 8, tag: "a" }
  3. { count: 8 }
  4. {}
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"}');
  1. Devuelve { mode: "fast" }.
  2. Devuelve { mode: "slow" }.
  3. Lanza un SyntaxError.
  4. Devuelve { mode: ["fast", "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])
);
  1. { north: 5, south: 7 }
  2. { north: 3, south: 5 }
  3. { north: 6, south: 10 }
  4. { 5: "north", 7: "south" }
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

¿Qué devuelve options.limit ?? 12?

const options = { limit: 0 };
  1. 12
  2. undefined
  3. 0
  4. null
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 */ }
};
  1. this.items
  2. item
  3. this.items.length
  4. this
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)];
  1. [27, 20]
  2. [6, 8]
  3. [6, 20]
  4. [27, 8]
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]);
  1. [7, 4]
  2. [[7, 3, 8, 2], 0]
  3. [7, 3]
  4. [7, 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
);
  1. true, true, false
  2. false, true, false
  3. false, false, false
  4. false, true, true
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"]]);
  1. La búsqueda usa una referencia a un objeto distinto.
  2. Map convierte ambas claves en cadenas distintas.
  3. Map ignora las claves de objeto al crear entradas.
  4. La clave debe convertirse primero en texto JSON.
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]);
  1. 1 y 1
  2. 3 y 2
  3. 2 y 4
  4. 2 y 3
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"]);
  1. '{"label":"Arc","count":3}'
  2. '{"label":"Arc"}'
  3. '["label"]'
  4. '{"label":"Arc","count":null}'
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));
  1. "object" y false
  2. "string" y true
  3. "object" y true
  4. "string" y false
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"; } };
  1. "function"
  2. "string"
  3. "object"
  4. "undefined"
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;
  1. 2, 9, 7
  2. 9, 9, 9
  3. 2, 9, 2
  4. 7, 9, 7
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 };
  1. ["z", "10", "02", "2", "a"]
  2. ["2", "10", "z", "02", "a"]
  3. ["02", "2", "10", "z", "a"]
  4. ["2", "02", "10", "z", "a"]
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;
  1. 540; sí, pasa a ser 350.
  2. 590; sí, pasa a ser 350.
  3. 540; no, sigue siendo 300.
  4. 420; sí, pasa a ser 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 };
  1. ["Aoak"]
  2. ["Aelm"]
  3. ["Belm"]
  4. Lanza un TypeError.
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;
}
  1. Ambas llamadas devuelven "light".
  2. La primera devuelve "light"; la segunda lanza TypeError.
  3. La primera lanza TypeError; la segunda devuelve null.
  4. La primera devuelve undefined; la segunda devuelve null.
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];
  1. [6, 8, 11]
  2. 8
  3. [11]
  4. [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);
  1. 3 y ["p", "r", "q"]
  2. 2 y ["q", "p"]
  3. 2 y ["p", "q"]
  4. 3 y ["p", "q", "r"]
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

¿Por qué falla JSON.parse('{"depthM":+7}')?
  1. Los números JSON no pueden empezar con un signo más.
  2. Los números JSON no pueden ser números enteros.
  3. Los nombres de propiedades JSON no pueden llevar mayúsculas.
  4. Los objetos JSON también deben contener una cadena.
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;
  1. "6" y "126"
  2. 6 y "126"
  3. 6 y 18
  4. undefined y NaN
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;
  1. true
  2. false
  3. undefined
  4. Lanza TypeError.
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));
  1. false, true, true
  2. true, true, true
  3. false, true, false
  4. false, false, false
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 });
  1. 5
  2. 12
  3. undefined
  4. 8
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);
  1. 13
  2. 41
  3. 36
  4. NaN
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];
  1. 8, 8, [8, 13]
  2. 8, 3, [8, 3, 13]
  3. 8, 3, [3, 13]
  4. 3, 8, [8, 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;
  1. "Old"; sí.
  2. "New"; sí.
  3. "New"; no.
  4. "Old"; no.
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);
}
  1. 1
  2. 2
  3. 4
  4. 3
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));
  1. 2 y 1
  2. 1 y 1
  3. 3 y 1
  4. 2 y 2
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}');
  1. "string"
  2. "object"
  3. "number"
  4. "undefined"
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un Map debe conservar por separado la clave numérica 3 y la clave de cadena "3" con los valores "n" y "s". ¿Qué par de conversiones las conserva mediante JSON?
  1. Escribir JSON.stringify(Object.fromEntries(m)); leer new Map(Object.entries(JSON.parse(text))).
  2. Escribir JSON.stringify([...m]); leer new Map(JSON.parse(text)).
  3. Escribir JSON.stringify(m); leer new Map(Object.entries(JSON.parse(text))).
  4. Escribir JSON.stringify([...m.keys()]); leer new Map(JSON.parse(text)).
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

79 Términos Clave, cada uno con su definición

A

Actualización inmutable
Una actualización inmutable construye contenedores nuevos para los datos que cambian y conserva los contenedores originales y los valores compartidos que no cambian.
Una función de devolución de llamada de map puede devolver una copia mediante propagación para el registro modificado y reutilizar todos los registros que no cambian.
Aplicación parcial
La aplicación parcial fija algunos argumentos ahora para crear una función que recibe los argumentos restantes cuando se llama más adelante.
multiply.bind(null, 4) crea una función que multiplica su siguiente argumento por cuatro.
Argumento de sangría
El argumento de sangría es el tercer argumento de stringify y controla los espacios o la cadena corta que se usan para dar formato al texto JSON anidado.
Pasar null como sustituto de serialización y 2 como tercer argumento hace que cada nivel anidado use dos espacios.

C

Cadena de caracteres en JSON
Una cadena de caracteres en JSON es un dato de texto delimitado por comillas dobles, con secuencias de escape para caracteres como las comillas y los saltos de línea.
Un valor de texto que contiene una comilla necesita una secuencia de escape dentro de las comillas dobles JSON que lo rodean.
Clave de índice de array
Una clave de índice de array es una cadena entera estándar desde 0 hasta 4 294 967 294, que se ordena numéricamente antes que las demás claves propias de cadena.
La clave "3" se ordena antes que "12" en Object.keys; "03" permanece entre las claves de cadena ordinarias.
Coalescencia nula
La coalescencia nula proporciona una alternativa solo cuando su operando izquierdo es null o undefined y conserva los demás valores falsos en contexto booleano.
settings.volume ?? 1 conserva un volumen explícito de cero, mientras que settings.volume || 1 lo sustituye.
Comprobación de la estructura de datos
Una comprobación de la estructura de datos verifica que un valor analizado tenga los campos, tipos de contenedor y tipos de valor que necesita el programa antes de usarlo.
Un JSON válido que contiene una cuenta como cadena aún necesita comprobarse antes de que un programa trate ese campo como un número.
Conjunto (Set)
Un Set es una colección de valores únicos de cualquier tipo que conserva el orden de inserción al recorrerse y no tiene posiciones indexadas.
Añadir "ready" dos veces conserva un valor, mientras que añadir dos registros separados con datos coincidentes conserva ambos.
Conjunto de referencias débiles (WeakSet)
Un WeakSet registra la pertenencia de objetos o símbolos no registrados sin mantener vivos los miembros que de otro modo serían inalcanzables y no se puede recorrer.
Un WeakSet puede marcar objetos procesados sin retenerlos solo porque se procesaron alguna vez.
Conversión de ida y vuelta
Una conversión de ida y vuelta escribe datos en una representación y los vuelve a leer, conservando solo la información que esa representación puede expresar.
Una conversión de ida y vuelta mediante JSON crea objetos nuevos y devuelve un Date como texto salvo que una conversión restaure su tipo.
Copia profunda
Una copia profunda crea datos anidados independientes además de un valor externo nuevo, según los tipos que admita el método de copia.
Después de una llamada compatible a structuredClone, editar un campo anidado copiado deja el campo original sin cambios.
Copia superficial
Una copia superficial crea un objeto o array externo nuevo y conserva las referencias a los objetos anidados almacenados en él.
Actualizar la dirección anidada de un registro copiado también puede actualizar la dirección compartida del registro original.

D

Datos anidados
Los datos anidados sitúan objetos o arrays dentro de otros objetos o arrays, por lo que una ruta debe seguir varios pasos para llegar a un valor.
report.readings[0].tempC lee una lista, su primer registro y después un campo de temperatura.
Desestructuración de arrays
La desestructuración de arrays lee valores de posiciones sucesivas de un iterable y los asigna mediante un patrón de corchetes.
const [low, high] = bounds; depende de que bounds coloque el valor menor antes que el mayor.
Desestructuración de objetos
La desestructuración de objetos lee propiedades seleccionadas y las asigna a variables mediante la correspondencia de sus nombres.
const { city, tempC } = reading; crea dos variables locales a partir de un registro meteorológico.
Diferencia
Una diferencia contiene los valores de una primera colección que no están en una segunda, por lo que intercambiar las colecciones puede cambiar el resultado.
active.difference(blocked) conserva los valores activos que no aparecen en el Set blocked.
Diferencia simétrica
Una diferencia simétrica contiene los valores presentes en exactamente una de dos colecciones y excluye todos los valores que comparten.
Comparar así dos Set de etiquetas encuentra las que pertenecen a una lista, pero no a ambas.

E

Elemento de resto en la desestructuración de arrays
Un elemento de resto en la desestructuración de arrays recopila los valores restantes en un array nuevo y debe cerrar el patrón.
const [leader, ...others] = names; separa el primer nombre de un array con los nombres restantes.
Encadenamiento de métodos
El encadenamiento de métodos llama a un método sobre el valor devuelto por la llamada anterior.
list.add("a").add("b") funciona cuando la primera llamada devuelve un objeto con el siguiente método add.
Encadenamiento opcional
El encadenamiento opcional detiene un acceso a propiedad, un acceso por índice o una llamada cuando el valor comprobado es null o undefined, y produce undefined.
record.owner?.name permite que falte owner sin intentar leer un nombre de undefined.
Entero seguro
Un entero seguro es un entero desde -9 007 199 254 740 991 hasta 9 007 199 254 740 991, rango en el que Number de JavaScript mantiene cada entero distinto y exacto.
Un identificador que supera el rango seguro puede enviarse como una cadena JSON para conservar todos sus dígitos.
Entrada de Map
Una entrada de Map asocia una clave con un valor y se gestiona con métodos de Map, de forma independiente de las propiedades ordinarias del objeto.
stock.set("tea", 4) cambia una entrada; stock["tea"] = 4 cambia una propiedad ordinaria.
Error de sintaxis (SyntaxError)
Un SyntaxError indica una sintaxis inválida, como un texto mal formado proporcionado a JSON.parse.
Una coma final en JSON externo puede capturarse con try...catch para que el programa pueda manejar el fallo.
Existencia de una propiedad
La existencia de una propiedad significa que una clave está presente, con independencia de que su valor almacenado sea verdadero o falso en contexto booleano, o undefined.
Un registro con 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)
Una función de transformación de valores analizados es una función de devolución de llamada de JSON.parse que transforma valores después de sus valores hijos y usa sus valores de retorno para sustituirlos o eliminarlos.
Una función de transformación puede restaurar un campo de fecha conocido y devolver sin cambios todos los valores no relacionados.
Función envolvente de tipo flecha
Una función envolvente de tipo flecha es una función de devolución de llamada de tipo flecha cuyo cuerpo realiza más adelante la llamada a método prevista y mantiene explícito el objeto receptor de esa llamada.
Pasar () => 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
structuredClone copia valores anidados de JavaScript compatibles, incluidas estructuras circulares, pero rechaza valores de función.
Se puede clonar un registro que contiene arrays ordinarios; incluir un método provoca un DataCloneError.

I

Identidad del objeto
La identidad del objeto es la distinción entre un objeto concreto y todos los demás, con independencia de que coincidan los valores de sus campos.
Dos registros creados por separado con id: 9 se comparan como distintos con === pese a tener los mismos datos.
Intersección
Una intersección contiene solo los valores presentes en ambas colecciones y deja fuera los que aparecen en una sola.
La intersección de los ID activos con los ID aprobados encuentra los que cumplen ambas condiciones de pertenencia.
Iterable
Un iterable proporciona una secuencia de valores a operaciones como for...of o la propagación en arrays.
Los arrays, las cadenas, los Map y los Set pueden desestructurarse de esta forma; un registro ordinario no.

J

JSON
JSON es un formato de texto independiente del lenguaje que representa objetos, arrays, cadenas, números, booleanos y null mediante una sintaxis estricta.
El texto {"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
Un literal de objeto crea un objeto directamente mediante llaves y propiedades clave-valor.
const reading = { tempC: 22 }; crea un registro que contiene una medición de temperatura.
Llamada sin receptor en modo estricto
Una llamada sin receptor en modo estricto invoca una función ordinaria estricta sin proporcionar un objeto receptor, por lo que su valor de this queda como undefined.
Desvincular un método en f y llamar a f() en un módulo puede fallar cuando intenta leer this.name.

M

Map
Un Map es una colección de entradas clave-valor con claves de cualquier tipo que conserva el orden en que sus claves se insertaron por primera vez.
La clave numérica 5 y la clave de cadena "5" siguen siendo entradas distintas cuando se almacenan en el mismo Map.
Mapa de referencias débiles (WeakMap)
Un WeakMap asocia valores a claves que son objetos o símbolos no registrados sin mantener vivas las claves que de otro modo serían inalcanzables.
Un WeakMap puede asociar metadatos a un objeto sin añadirle campos ni exponer una lista de entradas.
Método
Un método es una propiedad cuyo valor es una función y a la que se llama a través de un objeto.
Llamar a tracker.advance() ejecuta la acción del rastreador, mientras que leer tracker.advance devuelve una función.
Método apply
apply ejecuta una función inmediatamente con un valor de this explícito y un array que contiene sus argumentos ordinarios.
format.apply(reading, ["m", 2]) proporciona el mismo objeto receptor y los mismos valores que format.call(reading, "m", 2).
Método bind
bind devuelve una función nueva con un valor de this fijo y argumentos iniciales opcionales, y deja la ejecución para cuando se llame a la función nueva.
Guardar const next = meter.step.bind(meter); crea una función de devolución de llamada que conserva meter como objeto receptor.
Método call
call ejecuta una función inmediatamente con un valor de this explícito, seguido de argumentos ordinarios proporcionados uno por uno.
format.call(reading, "m", 2) proporciona a format el objeto receptor reading y dos argumentos separados.
Método desvinculado
Un método desvinculado es una función leída de un objeto y pasada o almacenada sin conservar el objeto en su expresión de llamada posterior.
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.
Analizar un registro con una cuenta numérica de 4 permite realizar operaciones aritméticas, mientras que una cuenta entre comillas sigue siendo una cadena.
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.
Agrupar registros por un objeto propietario compartido permite que esa misma referencia al propietario recupere su 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.
En código estricto, asignar el estado del nivel superior de un registro congelado lanza un TypeError.
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.
Transformar el valor de cada par y reconstruir el objeto permite convertir un registro completo de mediciones.
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.
Agrupar tareas por estado da un array para las tareas completadas y otro para las pendientes.
Método prestado
Un método prestado es una función ordinaria tomada de otro objeto y usada a través de un objeto receptor nuevo sin cambiar la propia función.
Asignar b.read = a.read permite que b.read() use los datos de b cuando la función lee mediante this.
Método toJSON
Un método toJSON devuelve la representación compatible con JSON elegida para un objeto, que stringify escribe en lugar del objeto original.
Un objeto de medición puede devolver un registro ordinario más pequeño que contenga los campos destinados al intercambio.

N

Nombre de propiedad calculado
Un nombre de propiedad calculado evalúa una expresión entre corchetes para nombrar una propiedad en un literal.
Con const code = "es";, { [code]: "Hola" } crea una propiedad llamada "es".
Notación de corchetes
La notación de corchetes evalúa la expresión dentro de los corchetes para seleccionar una clave de propiedad.
Con const field = "heightM";, person[field] selecciona la medición de altura de la persona.
Notación de punto
La notación de punto selecciona el nombre literal de propiedad que aparece después de un punto.
profile.name siempre selecciona la propiedad llamada "name", aunque exista una variable llamada name.

O

Objeto de opciones
Un objeto de opciones pasa ajustes nombrados a una función en lugar de depender de las posiciones de los argumentos.
Una función que recibe { color, size } permite indicar qué significa cada ajuste sin depender del orden de las posiciones.
Objeto receptor
Un objeto receptor es el objeto proporcionado como this en una llamada a un método ordinario.
En account.describe(), account es el objeto receptor que el método usa para leer sus campos.
Orden de inserción
El orden de inserción es la secuencia en que las claves o los valores distintos entran por primera vez en una colección, que se conserva al recorrer Map y Set.
Actualizar una entrada de Map mantiene su lugar; eliminarla y volver a insertar la clave la coloca al final.

P

Palabra clave this
La palabra clave this designa el contexto actual de una función; las funciones ordinarias suelen obtenerlo de la llamada y las funciones flecha conservan un contexto externo.
El mismo método de lectura ordinario no vinculado puede leer objetos diferentes cuando se llama a través de objetos receptores diferentes.
Par clave-valor
Un par clave-valor es una secuencia de dos elementos cuyo primer valor es una clave de propiedad o colección y cuyo segundo valor son los datos asociados.
Object.entries({ lake: 5 }) produce [["lake", 5]], listo para un bucle sobre claves y valores.
Parámetro de resto
Un parámetro de resto recopila los argumentos restantes de una función en un array real y debe ser el último parámetro de la declaración.
function total(...values) puede usar reduce con values incluso cuando la llamada no proporciona argumentos.
Patrón anidado
Un patrón anidado selecciona valores de una estructura interna mientras extrae los de su estructura externa.
const { owner: { name } } = item; necesita un objeto owner y declara solo name.
Patrón de cambio de nombre
Un patrón de cambio de nombre lee una propiedad en un nombre local diferente mediante dos puntos.
const { title: label } = page; crea label sin declarar una variable llamada title.
Posición omitida
Una posición omitida consume un valor sin nombrarlo en un patrón de desestructuración de arrays.
const [, second] = colors; omite el primer color y nombra solo el siguiente valor proporcionado.
Propagación de propiedades de objetos
La propagación de propiedades de objetos copia propiedades propias y enumerables en un literal nuevo; las apariciones posteriores sobrescriben los valores anteriores de la misma clave.
{ ...base, active: true } copia base y después proporciona el valor final de active.
Propagación de valores de iterables
La propagación de valores de iterables expande un iterable en elementos de array o argumentos de llamada separados, leyendo sus valores en secuencia.
Math.max(...measurements) proporciona cada elemento del array como argumento separado a la función.
Propiedad
Una propiedad relaciona una clave de objeto con un valor, incluidos datos o una función.
La propiedad active de { active: false } existe aunque su valor sea un booleano falso.
Propiedad abreviada
Una propiedad abreviada toma su nombre y valor de una variable con el mismo nombre.
Con una variable llamada city, el literal { city } crea el mismo campo que { city: city }.
Propiedad globalThis
globalThis proporciona una forma estándar de hacer referencia al objeto global, que las funciones ordinarias no estrictas usan en una llamada sin receptor.
El objeto global de un navegador es window, pero una llamada sin receptor a una función estricta sigue obteniendo undefined como this.
Propiedad propia
Una propiedad propia pertenece directamente a un objeto, por lo que una comprobación de propiedades propias no incluye las propiedades a las que se accede por herencia.
Object.hasOwn({}, "toString") es falso aunque "toString" in {} es verdadero.
Prueba de pertenencia
Una prueba de pertenencia pregunta si una clave o un valor está presente en una colección, con independencia de los datos almacenados bajo esa clave.
map.has(key) puede encontrar una entrada existente incluso cuando map.get(key) devuelve undefined.

R

Referencia
Una referencia conecta una variable o propiedad con un objeto, lo que permite que varios nombres accedan al mismo valor subyacente y lo modifiquen.
La asignación const backup = record; proporciona otra forma de acceder a record sin copiar sus campos.
Referencia circular
Una referencia circular es una ruta de referencias entre objetos que vuelve a un objeto ya presente en esa ruta y que JSON ordinario no puede codificar.
Añadir record.self = record hace que una llamada ordinaria a JSON.stringify lance un TypeError para ese registro.
Resto de propiedades de un objeto
El resto de propiedades de un objeto recopila en un objeto nuevo y superficial las propiedades propias y enumerables que aún no se han nombrado en un patrón de desestructuración.
const { password, ...publicRecord } = user; deja user intacto y excluye password de la copia.

S

Secuencia de escape
Una secuencia de escape usa una barra invertida y los caracteres que la siguen para representar un carácter especial o una unidad de código UTF-16 dentro de una cadena JSON.
Al serializar un mensaje con una nueva línea se escribe una secuencia de escape en lugar de colocar un salto de línea literal dentro de la cadena.
Serialización
La serialización convierte valores activos en una representación que se puede almacenar o intercambiar, como el texto JSON producido por stringify.
Un objeto de configuración debe serializarse antes de que un destino que solo acepta texto pueda recibir su estructura.
Sintaxis abreviada de métodos
La sintaxis abreviada de métodos define directamente un método ordinario por su nombre, parámetros y cuerpo en un literal.
El miembro reset() { this.n = 0; } define una acción sin dos puntos separados ni la palabra clave function.
Subconjunto
Un subconjunto es una colección cuyos valores pertenecen todos a otra colección, incluso cuando ambas colecciones son iguales.
Un Set de permisos requeridos es un subconjunto de los permisos concedidos solo cuando se ha concedido cada valor requerido.
Sustituto de serialización (replacer)
Un sustituto de serialización es el segundo argumento de stringify: un array de nombres de propiedades que se incluirán o una función que transforma los valores visitados.
Devolver undefined para una propiedad privada de objeto la omite, mientras que devolver el valor original conserva los demás datos.

T

this léxico
El this léxico es el valor de this circundante que conserva una función flecha donde se crea, sin que lo afecten un objeto receptor o una vinculación posteriores.
Una función flecha creada dentro de un método durante su ejecución puede conservar el objeto de ese método durante una función de devolución de llamada de array.

U

Unión
Una unión contiene todos los valores presentes en cualquiera de dos colecciones, con los valores compartidos incluidos una sola vez en el Set resultante.
Si un grupo tiene a Ana y Bo y otro tiene a Bo y Cai, su unión contiene a las tres personas.

V

Valor derivado
Un valor derivado se calcula a partir de otros datos almacenados, como un total a partir de líneas de artículos, y puede quedar desactualizado si se almacena por separado.
Calcular la distancia de una ruta a partir de sus tramos mantiene el resultado coherente después de que cambie un tramo.
Valor predeterminado en la desestructuración
Un valor predeterminado en la desestructuración sustituye un valor undefined seleccionado, incluido un campo o una posición ausentes.
En const { count = 2 } = { count: null };, el null explícito se conserva pese al valor predeterminado.

Sobre esta unidad

Por StudeliInformar de un error

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.

Comenzar