localStorage

Храним данные в браузере пользователя бесконечно долго (почти).

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

Это объект, хранящийся в window, который позволяет долговременно сохранять данные в браузере. Работает как хранилище данных в формате ключ-значение — при сохранении данных мы указываем имя поля, в которое должны быть сохранены данные, и затем используем это имя для их получения.

  • Значения хранятся в виде строк. При попытке сохранения других типов данных, они будут приведены к строке. Например, если записать число, то при чтении нам вернётся число, записанное в строку.
  • Не имеет ограничений по времени хранения, может быть очищен пользователем вручную или браузером при переполнении автоматически (браузеры на основе движка WebKit, например Safari, очищают localStorage, если к нему не обращались в течение 7 дней).
  • Максимальный объем данных ограничен размером 5MB.

Пример

Секция статьи "Пример"

Записываем данные:

        
          
          window.localStorage.setItem('name', 'Дока Дог')
          window.localStorage.setItem('name', 'Дока Дог')

        
        
          
        
      

При чтении ранее записанных данных по ключу name мы получим Дока Дог:

        
          
          const name = window.localStorage.getItem('name')console.log(name)// 'Дока Дог'
          const name = window.localStorage.getItem('name')
console.log(name)
// 'Дока Дог'

        
        
          
        
      

Повторная запись по тому же ключу приведёт к замене данных:

        
          
          window.localStorage.setItem('name', 'Собака Дока')const name = window.localStorage.getItem('name')console.log(name)// 'Собака Дока'
          window.localStorage.setItem('name', 'Собака Дока')

const name = window.localStorage.getItem('name')
console.log(name)
// 'Собака Дока'

        
        
          
        
      

Как это понять

Секция статьи "Как это понять"

Если вам нужно сохранить данные в браузере на долгое время и объем этих данных достаточно большой, то localStorage — то, что вам нужно. Данные будут храниться бессрочно и могут быть стёрты только в двух случаях: при превышении лимита по размеру данных или очистке хранилища пользователем или программно.

Как пишется

Секция статьи "Как пишется"

Запись

Секция статьи "Запись"

Для записи используйте метод setItem('ключ', 'значение'). Он принимает два строковых параметра: ключ, по которому будет сохранено значение, и само значение.

        
          
          window.localStorage.setItem('name', 'Дока Дог')
          window.localStorage.setItem('name', 'Дока Дог')

        
        
          
        
      

Чтение

Секция статьи "Чтение"

За чтение отвечает getItem('ключ') c одним параметром, который указывает на ключ для чтения и возвращает полученное значение из хранилища. Если по этому ключу нет значения, то метод вернёт null.

        
          
          window.localStorage.getItem('name') // вернет 'Дока Дог'window.localStorage.getItem('user') // вернет `null`
          window.localStorage.getItem('name') // вернет 'Дока Дог'
window.localStorage.getItem('user') // вернет `null`

        
        
          
        
      

Удаление

Секция статьи "Удаление"

Удаляет запись из хранилища removeItem('ключ'). Он успешно выполнится даже если указанного ключа не существует в хранилище.

        
          
          window.localStorage.removeItem('name')window.localStorage.removeItem('user')
          window.localStorage.removeItem('name')
window.localStorage.removeItem('user')

        
        
          
        
      

Очистка хранилища

Секция статьи "Очистка хранилища"

Метод clear() очищает хранилище полностью.

        
          
          window.localStorage.clear()
          window.localStorage.clear()

        
        
          
        
      

Количество полей в хранилище

Секция статьи "Количество полей в хранилище"

Используя свойство length, можно узнать, сколько всего полей было записано в хранилище.

        
          
          console.log(window.localStorage.length);// 0
          console.log(window.localStorage.length);
// 0

        
        
          
        
      

Получение ключа по индексу

Секция статьи "Получение ключа по индексу"

Метод key() получает ключ по индексу. Значения в хранилище хранятся в порядке их добавления, поэтому значение, добавленное первым, будет храниться в позиции 0 и так далее.

        
          
          window.localStorage.setItem('name', 'Дока Дог')console.log(window.localStorage.key(0));// 'name'
          window.localStorage.setItem('name', 'Дока Дог')
console.log(window.localStorage.key(0));
// 'name'

        
        
          
        
      

Таким образом, используя количество полей в хранилище и получение ключа по индексу, можно организовать перебор всех значений в хранилище.

        
          
          const localStorageSize = window.localStorage.lengthfor (let i = 0; i < localStorageSize; i++) {  console.log(      window.localStorage.getItem(localStorage.key(i))  )}
          const localStorageSize = window.localStorage.length
for (let i = 0; i < localStorageSize; i++) {
  console.log(
      window.localStorage.getItem(localStorage.key(i))
  )
}

        
        
          
        
      

События

Секция статьи "События"

При установке значения в хранилище срабатывает глобальное событие storage, с помощью которого можно отслеживать изменения в хранилище.

💡 Событие происходит только на других открытых страницах текущего сайта.

Событие содержит свойства:

  • key - ключ, который был изменён (при вызове метода clear(), ключ будет null);
  • oldValue - старое значение, записанное в поле;
  • newValue - новое значение, записанное в поле;
  • url - адрес страницы, на которой вызвано изменение.
        
          
          window.addEventListener('storage', function (evt) {  console.log(evt)})
          window.addEventListener('storage', function (evt) {
  console.log(evt)
})

        
        
          
        
      

На практике

Секция статьи "На практике"

Павел Минеев советует

Секция статьи "Павел Минеев советует"

🛠 При помощи localStorage можно сохранять данные, относящиеся к пользователю, не храня их на сервере. В следующем примере мы будем запоминать размер шрифта на сайте и восстанавливать размер из хранилища, если он был изменён до этого.

Открыть демо в новой вкладке

🛠 Можно использовать для синхронизации нескольких открытых в браузере вкладок. При изменении размера шрифта в одной вкладке мы узнаем об этом во всех остальных и тоже изменим размер.

        
          
          function changePageFontSize(size) {  document.style.fontSize = `${size}px`}window.addEventListener('storage', function (evt) {  if (evt.key === 'pageFontSize') {    changePageFontSize(evt.newValue)  }})
          function changePageFontSize(size) {
  document.style.fontSize = `${size}px`
}

window.addEventListener('storage', function (evt) {
  if (evt.key === 'pageFontSize') {
    changePageFontSize(evt.newValue)
  }
})

        
        
          
        
      

🛠 Иногда нам нужно сохранить не просто текст, а целую структуру данных, и в этом нам поможет JSON.stringify().

        
          
          const user = {  name: 'Дока Дог',  avatarUrl: 'mascot-doka.svg'}localStorage.setItem('user', JSON.stringify(user))
          const user = {
  name: 'Дока Дог',
  avatarUrl: 'mascot-doka.svg'
}

localStorage.setItem('user', JSON.stringify(user))

        
        
          
        
      

И после чтения парсим:

        
          
          function readUser() {  const userJSON = localStorage.getItem('user')  if (userJSON === null) {    return undefined  }  // Если вдруг в хранилище оказался невалидный JSON предохраняемся от этого  try {    return JSON.parse(userJSON)  } catch (e) {    localStorage.removeItem('user')    return undefined  }}console.log(readUser())// {//  name: 'Дока Дог',//  avatarUrl: 'mascot-doka.svg'// }
          function readUser() {
  const userJSON = localStorage.getItem('user')

  if (userJSON === null) {
    return undefined
  }

  // Если вдруг в хранилище оказался невалидный JSON предохраняемся от этого
  try {
    return JSON.parse(userJSON)
  } catch (e) {
    localStorage.removeItem('user')
    return undefined
  }
}

console.log(readUser())
// {
//  name: 'Дока Дог',
//  avatarUrl: 'mascot-doka.svg'
// }

        
        
          
        
      

🛠 Если ваш сайт использует скрипты аналитики или другие внешние библиотеки, то они также имеют доступ к хранилищу. Поэтому лучше именовать ключи для записи в хранилище с префиксом в едином стиле. Например, при записи чего-либо на таком сайте я бы выбрал префикс YD_{название ключа}, тогда можно сгруппировать только нужные значения или отфильтровать их в инструментах разработчика.

🛠 Используйте функции-обёртки для предотвращения ошибок, связанных с неудачными попытками записи, отсутствием localStorage в браузере и дублированием кода.

        
          
          function getItem(key, value) {  try {    return window.localStorage.getItem(key)  } catch (e) {    console.log(e)  }}function setItem(key, value) {  try {    return window.localStorage.setItem(key, value)  } catch (e) {    console.log(e)  }}function setJSON(key, value) {  try {    const json = JSON.stringify(value)    setItem(key, json)  } catch (e) {    console.error(e)  }}function getJSON(key) {  try {    const json = getItem(key)    return JSON.parse(json)  } catch (e) {    console.error(e)  }}
          function getItem(key, value) {
  try {
    return window.localStorage.getItem(key)
  } catch (e) {
    console.log(e)
  }
}

function setItem(key, value) {
  try {
    return window.localStorage.setItem(key, value)
  } catch (e) {
    console.log(e)
  }
}

function setJSON(key, value) {
  try {
    const json = JSON.stringify(value)

    setItem(key, json)
  } catch (e) {
    console.error(e)
  }
}

function getJSON(key) {
  try {
    const json = getItem(key)

    return JSON.parse(json)
  } catch (e) {
    console.error(e)
  }
}