Поведение хранилища localForage напрямую зависит от используемого драйвера — IndexedDB, WebSQL или localStorage. Ключевой момент заключается в том, что разные драйверы используют разные механизмы сериализации данных: от полноценного структурного клонирования до JSON-подобного преобразования. Именно поэтому одни и те же типы данных могут сохраняться по-разному и возвращаться в различном виде.
Значение undefined не имеет представления в форматах
сериализации, используемых в браузерных хранилищах.
В контексте localForage:
undefined полностью исключается из результата
JSON.stringifynull в зависимости от внутреннего пути обработкиПоведение можно обобщить так: undefined не является сохраняемым типом данных
localforage.setItem('key', undefined).then(() => {
return localforage.getItem('key');
}).then(value => {
// value, скорее всего, будет null или undefined
});
На практике это означает, что undefined не должен
использоваться как значение состояния, требующее восстановления. Вместо
него применяются явные маркеры:
null — отсутствие значенияОбъект Date является одним из наиболее проблемных типов
с точки зрения сериализации, поскольку его корректная передача зависит
от поддержки структурного клонирования.
IndexedDB использует алгоритм structured clone, который поддерживает
Date как полноценный объект. Это означает:
DategetTime, toISOString остаются
доступными без преобразованийconst value = new Date();
await localforage.setItem('date', value);
const restored = await localforage.getItem('date');
// restored instanceof Date === true
localStorage работает через строковое представление, обычно JSON-сериализацию:
Date преобразуется в строку ISODate теряетсяawait localforage.setItem('date', new Date());
const restored = await localforage.getItem('date');
// "2026-06-03T10:15:30.000Z" (строка)
const date = new Date(restored);
Таким образом, поведение Date не является стабильным
между драйверами, и логика приложения должна учитывать возможное
приведение типов.
Map — сложная структура данных, не совместимая с
JSON-сериализацией, но поддерживаемая structured clone алгоритмом.
Современные браузеры поддерживают Map в structured
clone, что даёт следующие свойства:
Mapconst map = new Map();
map.set('a', 1);
map.set({ key: 'b' }, 2);
await localforage.setItem('map', map);
const restored = await localforage.getItem('map');
// restored instanceof Map === true
При fallback на localStorage:
Map не сериализуется корректно{} или теряет
содержимоеЭто делает Map ненадёжным типом для
кросс-драйверного хранения без нормализации данных.
Set аналогичен Map по отношению к
structured clone, но имеет свои особенности поведения при
сериализации.
Поддержка structured clone позволяет сохранять:
Setconst set = new Set([1, 2, 3]);
await localforage.setItem('set', set);
const restored = await localforage.getItem('set');
// restored instanceof Set === true
При использовании JSON-подобной сериализации:
Set теряет свою природуArray.fromconst restored = await localforage.getItem('set');
const set = new Set(Array.isArray(restored) ? restored : []);
| Тип данных | IndexedDB | localStorage |
|---|---|---|
| undefined | не сохраняется / теряется | не сохраняется |
| Date | сохраняется как Date | превращается в строку |
| Map | сохраняется корректно | теряется или искажается |
| Set | сохраняется корректно | теряется или искажается |
localForage автоматически выбирает наиболее подходящий драйвер в зависимости от окружения. Это создаёт скрытую неоднородность поведения:
Это приводит к необходимости учитывать деградацию типов при проектировании данных, особенно для:
Для обеспечения предсказуемости часто используется явная сериализация сложных типов до записи в localForage.
await localforage.setItem('timestamp', Date.now());
const map = new Map([['a', 1]]);
await localforage.setItem('map', Array.from(map.entries()));
const set = new Set([1, 2, 3]);
await localforage.setItem('set', Array.from(set));
const value = undefined;
await localforage.setItem('value', value ?? null);
const entries = await localforage.getItem('map');
const map = new Map(entries);
const arr = await localforage.getItem('set');
const set = new Set(arr);
При хранении сложных объектов, содержащих смесь типов:
localForage не выполняет автоматическое восстановление типов на уровне JSON-reviver, за исключением возможностей structured clone в IndexedDB. Это означает:
Любая типизация должна быть реализована на уровне приложения или слоя абстракции над localForage.
Поведение можно свести к двум режимам:
Structured Clone (IndexedDB):
JSON-подобная сериализация (localStorage):