JavaScript - всё о localStorage и sessionStorage

Александр Мальцев
79K
1
Содержание:
  1. Веб-хранилище. Назначение localStorage и sessionStorage
  2. Объекты localStorage и sessionStorage
  3. Тест скорости выполнения операций с данными в localStorage и cookie
  4. Комментарии

В этой статье мы познакомимся с хранилищами браузера LocalStorage и SessionStorage. Рассмотрим их назначение, отличие друг от друга, и от cookies, а также самое основное разберём методы JavaScript для работы с ними.

Веб-хранилище. Назначение localStorage и sessionStorage

Веб-хранилище - это данные, хранящиеся локально в браузере пользователя. Существует 2 типа веб-хранилищ:

  • LocalStorage;
  • SessionStorage.

В них вы можете хранить информацию в формате ключ-значение. Ключ и значение – это всегда строки.

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

Отличие между этими хранилищами сводится только к периоду времени, в течение которого они могут хранить данные, помещенные в них:

  • SessionStorage – выполняет это в течение определённого промежутка времени (сессии). Закрытие вкладки или браузера приводит их к удалению. При этом данные в SessionStorage сохраняются при обновлении страницы.
  • LocalStorage – осуществляет это в течение неограниченного времени. Они сохраняются при перезагрузке браузера и компьютера. Их длительность хранения ничем не ограничена. Но, хоть эти данные могут храниться бесконечно в браузере, обычный пользователь может их очень просто удалить, например выполнив очистку истории (при включенной опции «файлы cookie и другие данные сайтов»).

Хранилище LocalStorage похоже на cookies. Оно также применяется для хранения данных на компьютере пользователя (в браузере). Но кроме общих сходств имеется также и много отличий.

Cookies vs. LocalStorage: В чём разница

Отличия между cookies и LocalStorage:

  • по месту хранения (куки и данные LocalStorage хранятся на компьютере пользователя в браузере);
  • по размеру (cookies ограничены 4 Кбайт, а размер LocalStorage - 5 Мбайт);
  • по включению этих данных в HTTP-заголовок (куки в отличие от данных локального хранилища включаются в состав запроса при отправке его на сервер, а также сервер их может добавлять в ответ при отправке его клиенту; таким образом cookies являются частью HTTP-протокола, и увеличивают объём передаваемых данных от клиента серверу и обратно);
  • по доступности данных (печеньки можно прочитать и установить как на сервере, так и на клиенте; на клиенте доступны все куки, кроме тех, у которых установлен флаг HttpOnly; LocalStorage доступны только в браузере посредством JavaScript API);
  • по времени хранения данных (куки хранятся ограниченное время (до конца сеанса или истечения указанной даты), нахождение данных в локальном хранилище не ограничено по времени);
  • по удобству использования в JavaScript (работа с LocalStorage в JavaScript организовано намного удобнее чем с cookies);
  • по необходимости информирования пользователей Евросоюза (при использовании cookies сайт в ЕС должен получать на это разрешение от пользователей; для данных локального хранилища это не требуется);
  • по назначению (куки в основном используются для управления сеансом, персонализации и отслеживания действий пользователя, в то время как LocalStorage применяется в качестве обычного локального хранилища информации на компьютере пользователя).

Что использовать: LocalStorage или cookies? На самом деле, ответ на этот вопрос очень прост. Если вам не нужно отправлять данные с каждым HTTP-запросом на сервер, то в этом случае лучше использовать для хранения данных LocalStorage.

Безопасность данных

Хранилище LocalStorage привязана к источнику (домену, протоколу и порту). Данные, находящиеся в некотором источнике, доступны для всех сценариев страниц этого же источника. Из сценария, находящегося в одном источнике, нельзя получить доступ к данным, определяемым другим источником.

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

Итоги

Основные характеристики LocalStorage и SessionStorage:

  • данные хранятся в виде пар «ключ-значение»;
  • хранить можно только строки;
  • если вам необходимо хранить в этих хранилищах массивы и объекты, то сначала вы должны их превратить в строки, например, используя метод JSON.stringify. Для преобразования строки обратно в массив или объект, можно использовать JSON.parse. Подробнее об этом позже.

Объекты localStorage и sessionStorage

Работа с веб-хранилищами в JavaScript выполняется через объекты localStorage и sessionStorage. Объекты localStorage и sessionStorage находятся в глобальном объекте window.

Они имеют одинаковый набор свойств и методов:

  • getItem(key) - получить значение элемента хранилища по key;
  • setItem(key,value) - установить для key указанное значение value (если в хранилище уже есть данные с этим ключом, то они будут переписаны);
  • removeItem(key) - удалить элемент по key;
  • clear() - удалить все элементы;
  • key(index) - получить элемент по его индексу (в основном используется для перебора);
  • length - свойство, с помощью которого можно получить количество элементов в хранилище;

Примеры

1. Пример, в котором добавим элемент в веб-хранилище, получим его значение по ключу, а затем удалим его:

// 1 - добавим в LocalStorage элемент с ключом «bgColor» и значением «green»
localStorage.setItem('bgColor', 'green');
// 2 - получим значение по ключу «bgColor» и сохраним его в переменную «bgColor»
var bgColor = localStorage.getItem('bgColor');
// 3 - удалим элемент из хранилища по ключу
localStorage.removeItem('bgColor');

2. Пример, в котором удалим все элементы из хранилища:

localStorage.clear();

3. Пример, в котором перебём все элементы LocalStorage:

<div id="result"></div>
...
<script>
  var output = '';

  // localStorage.length - количество элементов в хранилище
  for (var i = 0, length = localStorage.length; i < length; i++) {
    // localStorage.key(i) - получение ключа элемента по его индексу
    output += 'Ключ: ' + localStorage.key(i) + "; Значение: " + localStorage.getItem(localStorage.key(i)) + ".&lt;br&gt;";
  }
  
  document.querySelector('#result').innerHTML = output;
</script>

4. Пример, в котором запишем JavaScript объект в LocalStorage:

// 1 - JavaScript объект
var obj = {
  prop1: 'value1',
  prop2: 'value2',
  prop3: 'value3'
  // ...
}
// 2 - Сохраним JavaScript объект в LocalStorage преобразовав его в строку JSON
localStorage.setItem('mykey', JSON.stringify(obj));

// ...

// 3 - Получим из LocalStorage значение по ключу «mykey», если он там есть (т.е. если его значение не равно null)
if (localStorage.getItem('mykey')) {
  // 4 - Получим из LocalStorage значение по ключу «mykey», преобразуем его с помощью метода JSON.parse в JavaScript объект
  obj = JSON.parse(localStorage.getItem('mykey'));
}

Из этого примера видно, что если вам нужно в LocalStorage записать объект, то одним из вариантов решения этой задачи может стать его сериализация в строку JSON с помощью функции JSON.stringify.

5. Пример, в котором проверим поддерживает ли браузер веб-хранилище?

if (typeof(Storage) !== 'undefined') {
  // код для localStorage
} else {
  // браузер не поддерживает веб-хранилище
}

6. Пример, в котором покажем как можно добавить дату к записям, а затем её использовать для их очистки (например, удалять записи, если со времени её записи прошло уже более 30 дней):

// пример данных, которые мы получили из LocalStorage
var
  viewsItems = [
    {
      id: '1608467',
      title: '6.26" Смартфон Huawei Nova 5T 128 ГБ фиолетовый',
      timestamp: 1583020800000 // 01.03.2020
    },
    {
      id: '1348312',
      title: '6.1" Смартфон Huawei P30 128 ГБ синий',
      timestamp: 1585872000000 // 03.04.2020
    },
    {
      id: '1394820',
      title: '6.1" Смартфон Apple iPhone 11 128 ГБ черный',
      timestamp: 1586476800000 // 10.04.2020
    }
  ],
  newViewsItems = [];

// сформируем из массива viewsItems новый массив newViewsItems только из тех данных, timestamp которых не более 30 дней
for (var i = 0, length = viewsItems.length; i < length; i++) {
  if (viewsItems[i].timestamp > (Date.now() - 1000 * 60 * 60 * 24 * 30)) {
    newViewsItems.push(viewsItems[i]);
  }
}

// например, если текущая дата 11.04.2020, то в массив newViewsItems попадут все элементы, кроме первого

// сохраним новый массив, очищенный от старых записей в LocalStorage
localStorage.setItem('viewsItems', JSON.stringify(newViewsItems));

Рассмотрим быстродействие (в процентном отношении), которое имеют методы при выполнении операций с данными в localStorage и cookie.

В качестве браузеров будем использовать Chrome 47, Firefox 42 и IE11, работающие на операционной системе Windows 7.

Тест 1. Быстродействие методов, осуществляющих чтение данных из localStorage и cookie.

Быстродействие методов, осуществляющих чтение данных из localStorage и cookie

Вывод: Современные браузеры выполняют операции чтения данных из хранилища localStorage намного быстрее, чем из cookie. В браузере Google Chrome это разница достигает нескольких десятков раз, в Firefox – 9 раз и в IE 11 – 2 раза.

Тест 2. Быстродействие методов, осуществляющих запись данных в localStorage и cookie.

Быстродействие методов, осуществляющих запись данных в localStorage и cookie

Вывод: Операции записи данных в хранилище localStorage выполняются быстрее, чем в cookie, но не настолько как при чтении. Браузер Google Chrome выполняет запись в localSorage быстрее в 1.6 раза, Firefox в 7 раз, Internet Explorer 11 показал равнозначный результат.

Тест 3. Быстродействие браузеров, осуществляющих запись данных в localStorage и их чтение.

Быстродействие браузеров, осуществляющих чтение данных из localStorage Быстродействие браузеров, осуществляющих запись данных в localStorage

Вывод: Firefox показал довольно хорошие преимущества в быстродействии перед другими браузерами, и это касается не только технологии localStorage, но и cookie (диаграммы не приводятся).

Комментарии ()

  1. Stanislav
    16 июня 2020, 17:07
    Здавствуйте, ситуация такова, нужно отследить ссылку по которой пользователь попал на сайт и записать в скрытое поле ввода, при этом есть условие, он может переходить по страницам сайта, но нужна именно ссылка по которой он папал на сайт, я пробовал использовать данный код, но получается записать только последнюю ссылку с которой перешли на страницу:
    $(document).ready(function() {
     sessionStorage.setItem('link', document.referrer);
      var sessionref = sessionStorage.getItem('link');
      if (sessionref) {
        $('input[name ="referer"]').val(sessionref);
      } else {
      $('input[name ="referer"]').val('error');
      }
    });
    

    Может подскажете решение, если оно существует?
    1. Александр Мальцев
      17 июня 2020, 08:51
      Привет! sessionStorage сохраняет данные только в пределах вкладки. Если пользователь откроет ссылку в новой вкладке, то там этих данных уже не будет.

      В коде вам нужно сначала проверить, если ли данные в LocalStorage, а потом туда уже что-то записывать:
      $(function() {
        var sessionref = sessionStorage.getItem('link');
        if (sessionref === null) {
          sessionref = document.referrer;
          sessionStorage.setItem('link', sessionref);
        }
        if (sessionref) {
          $('input[name ="referer"]').val(sessionref);
        } else {
        $('input[name ="referer"]').val('error');
        }
      });
      
    2. Nik
      12 апреля 2020, 13:32
      Разница в быстродействии очевидна, теперь ясно почему не cookie. Хорошая статья, наглядно видно!
      1. Александр Мальцев
        12 апреля 2020, 14:00
        На это не стоит ориентироваться, сейчас результаты могут быть другими. Это зависит от того, как это физически реализовано в конкретном браузере. Если стоит выбор, то лучше просто задать себе вопрос: «Нужны ли мне эти данные на сервере и буду ли я их как-то учитывать при строительстве страницы на стороне сервера? Если нет, то тут однозначно LocalStorage.
      2. Дмитрий
        07 июня 2019, 22:41
        Здравствуйте Александр, использую на одном из своих шаблонов http://laraweb.ru/autoshop/shop/ переключатель — сетка/список, сделал сохранение переключения через localStorage, но возникла проблема, там слева фильтр на аджакс, когда я делаю выборку, нажимаю найти, то мне выдается результат товаров, но при этом перестает работать переключатель список/сетка, можно ли как то решить проблему, чтоб сохранялся рабочий переключатель?
        1. Николай
          08 марта 2017, 10:06
          Спасибо за статью, такой вопрос, а где физически сохраняются данные? И нельзя ли где-то в переменных это прописывать. А также, файлы куки как мы знаем легко очищаются в винде, что с этими данными? Ну и еще, если я сделал мобильное приложение на основе HTML5, где там сохраняются данные?
          1. Александр Мальцев
            08 марта 2017, 16:02
            Это зависит от браузера. Chrome для LocalStorage использует SQLite. Физически (например, в Windows) они находятся в файлах, которые расположены каталоге: AppData\Local\Google\Chrome\User Data\Default\Local Storage\.
            Эти файлы, как и cookies можно очистить (chrome://settings/cookies#cont). Надёжное хранилище — это только база данных на сервере.
            1. Николай
              08 марта 2017, 16:59
              Спасибо за быстрый ответ, я примерно так и думал, но на всякий случай уточнил
          2. Larisa
            07 ноября 2016, 18:08
            здравствуйте, Александр! спасибо за ваш чудесный блог и оперативные ответы!
            у меня такая проблема: есть боковое меню, открытие/закрытие которого регулируется классами тэга body: site-menubar-unfold / site-menubar-fold соответственно. надо, чтобы при переходе на новую страницу выбранное состояние сохранялось. как это реализовать с помощью sessionStorage я примерно поняла, но как отследить изменение url? нагуглила только функцию hashchange, но «Событие hashchange генерируется когда изменяется идентификатор фрагмента URL (т.е. часть URL следующая за символом #, включая сам символ #).» а у меня меняется не идентификатор, а html-страница. например, localhost/project/idex.html -> localhost/project/stat.html
            спасибо)
            1. Александр Мальцев
              08 ноября 2016, 10:19
              Здравствуйте, Larisa. Спасибо за отзыв. Лучше всего событие «повесить» на момент когда происходит открытие или закрытие бокового меню. И когда это происходит сохранять состояние этого меню в localstorage. А при загрузке новой страницы считывать это состояние и устанавливать его боковому меню.
              1. Larisa
                11 ноября 2016, 17:40
                вот что получилось с хранилищем, но не могу придумать, как прикрутить еще и загрузку новой страницы…
                    // получаем адрес страницы, на которой находимся
                    var pageAddress = location.href; 
                
                    // записываем в хранилище класс, отвечающий за состояние меню
                    if ($('body').hasClass('site-menubar-unfold')){
                      sessionStorage.setItem("menuState","open"); 
                    }
                    else if ($('body').hasClass('site-menubar-fold')){
                      sessionStorage.setItem("menuState","close");
                    }
                
                    //достаем из хранилища класс и, если он отличается от 'site-menubar-unfold', присваиваем его элементу body
                    var menuState = sessionStorage.getItem("menuState");
                    if (menuState == "close"){
                      $("body").removeClass('site-menubar-unfold');
                      $("body").addClass('site-menubar-fold');
                    }
                
                1. Александр Мальцев
                  12 ноября 2016, 06:39
                  Вам необходимо разобраться каким образом класс site-menubar-unfold или site-menubar-fold появляется у элемента body. Т.е. при каком событии это происходит (например, при клике или как-то по-другому).
                  После этого вам необходимо добавить в обработчик этого события блок кода JavaScript, в котором происходит запись информации в хранилище.

                  Второй блок, в котором происходит считывание информации, необходимо выполнять после загрузки страницы:
                  $(function(){
                    // код, который выполнится после загрузки страницы
                  });
                  
                  1. Larisa
                    12 ноября 2016, 10:48
                    классы эти появляются у элемента body по клику, но во время работы на одной странице пользователь может гонять меню туда-сюда сколько угодно — важно, какой класс у элемента body при переходе на новую страницу — т.е. при смене url — и на новую страницу этот же класс нужно перенести…
                    1. Александр Мальцев
                      12 ноября 2016, 14:30
                      А что значит при смене url. Пользователь может попасть на страницу посредством поиска, социальных сетей или какой-то ссылки, расположенной на другом сайте. К тому же в JavaScript нет такого события. Поэтому правильно сохранять состояния меню в тот момент, когда пользователь его изменяет. Чтобы в следующий раз, когда пользователь попадёт на сайт, предоставить ему сохранённое состояние.
                      Есть событие, которое происходит при выгрузке страницы, но его поддержка зависит от браузера. Поэтому его не рекомендуется использовать. Применяется оно так:
                      $(window).unload(function() {
                        // сохраняете состояние меню
                      });
                      
                      1. Larisa
                        12 ноября 2016, 14:46
                        еще раз большое спасибо вам! действительно, нужно было клик отслеживать)
                        а страница может меняться при переходе по ссылкам внутри нее же или в том же меню
                          //проверяем поменялся ли URL страницы в данной вкладке браузера
                          var pageAddress = location.href;
                          var oldAddress = '';
                          if (localStorage.getItem('pageAddress')) {
                            oldAddress = localStorage.getItem('pageAddress');
                          }
                          localStorage.setItem('pageAddress', pageAddress);
                        
                          var menuState = '';
                          $('#toggleMenubar').click(function(){
                            // записываем в хранилище класс, отвечающий за состояние меню
                            if ($('body').hasClass('site-menubar-unfold')){
                              localStorage.setItem('menuState', 'close');
                            }
                            else if ($('body').hasClass('site-menubar-fold')){
                              localStorage.setItem('menuState', 'open');
                            }
                          });
                          menuState = localStorage.getItem('menuState');
                        
                          if (oldAddress == pageAddress) {
                            //страница не поменялась - делаем действия, которые нам нужны при том же адресе
                            if (menuState == 'close'){
                              $("body").removeClass('site-menubar-unfold');
                              $("body").addClass('site-menubar-fold');
                            }
                          } else {
                            //страница поменялась или открыта впервые - делаем действия, которые нам нужны при новом адресе
                            if (menuState == 'close'){
                              $("body").removeClass('site-menubar-unfold');
                              $("body").addClass('site-menubar-fold');
                            }
                          }
                        
                2. Larisa
                  10 ноября 2016, 11:37
                  а каким образом отслеживать изменение страницы?
              2. Vlad
                08 февраля 2016, 17:09
                Данные из session storage удаляются только после закрытия вкладки, закрытие браузера не удаляет данные
                1. ctac
                  03 декабря 2015, 13:22
                  Спасибо за статью, но такой информации в сети полно, как работать, для чего нужно и тд. Вы бы провели аналитику, например чем предпочтительней использовать localStorage вместо cookie? Как перестать пользоваться cookie и перейти на localStorage? Я думаю, такой материал был бы куда интересней и полезней
                  1. Александр Мальцев
                    04 декабря 2015, 16:59
                    Спасибо Стас за комментарий. В конце статьи добавил 2 раздела, рассказывающие и показывающие отличия между cookie и Web Storage, а также диаграммы по быстродействию.
                  Войдите, пожайлуста, в аккаунт, чтобы оставить комментарий.