Какие в JS есть решения хранения данных, которые доступных из любого места приложения?

Пишу скрипт на нативном JS, где нужные данные появляются в функции некоторого уровня вложенности, но должны быть доступными из любого уровня вложенности.

Среди моих познаний JS только один вариант реализации - хранить в localStorage.

То есть я помещаю данные в localStorage:

localStorage.setItem('answer', JSON.stringify(answer));

а потом забираю их оттуда:

localStorage.getItem("answer");

Говорят, localStorage синхронный, то есть останавливающий работу остальных скриптов пока сам выполняется. Наверняка есть ещё какие-то подводные камни. Мне даже не нужно хранить данные сессии; я их даже вынужденно удаляю при загрузке страницы. Более того меня не покидает чувство, что решение хранить промежуточные данные через localStorage - не изящное, и есть куда более профессиональное.

Есть возможность создать какое-то хранилище (массив, объект или ещё что-то), куда можно и записать, и считать данные, не использую localStorage? Например, данные появляются на 10-ом уровне вложенности, но доступны из любого места приложения?

ПС. Мне кажется, что решение прям очень простое, из азов JS, я прав?


Ответы (2 шт):

Автор решения: Vasily

Думаю в Вашем случае подойдет глобальная переменная:

window.STORAGE = {}

console.log(STORAGE)
// {}

STORAGE.data = 10101010

console.log(STORAGE)
// {
//   "data": 10101010
// }

В последней версии ECMAScript появилась возможность универсального обращения к глобальным объектам glabalThis:

// браузер
window

// nodejs
global

// web-worker
self

Теперь мы можем удобно обращаться к нему, не беспокоясь о том что нужно менять window на global или self, если например нужно запустить скрипт на Node или WebWorker соответственно:

globalThis.STORAGE = {}

console.log(STORAGE)
// {}

STORAGE.data = 10101010

console.log(STORAGE)
// {
//   "data": 10101010
// }

Если нужно что более "серьезное", то стоит посмотреть в сторону Redux.

→ Ссылка
Автор решения: OPTIMUS PRIME

Если такой объект всего один, можно банально создать глобальную константу в самом начале программы и использовать его как связывающее звено между разными функциями. Скажем:

const ROOT = {};

(function() {
  let colors = ["#b22", "#382", "#17a"];
  let i = 0;
  
  ROOT.next_color = function() {
    return colors[ i = (i + 1) % colors.length ];
  };
})();

(function() {
  document.addEventListener("click", function() {
    document.body.style.backgroundColor = ROOT.next_color();
  });
})();
« Клик »

При этом, если таких переменных станет многовато, это ничем не лучше использования обычных глобальных переменных. Захочется как-то группировать общие переменные в дополнительные вложенные объекты, чтобы случайно названия не пересекались.

Во время писанины мелкой браузерной игрушки, появилась необходимость пары десятка подобных объектов (классов). Везде таскать с собой "приставку" типа ROOT.animate.add(), ROOT.battle - не очень удобно. Как вариант - можно было в отдельном файле заранее глобально объявить все такие объекты, и уже в другом месте их заполнять.

Другой вариант (был принят как финальный), из каждой "папки" объявить свой глобальный объект через window. А чтобы не париться с вызовами функций, которые еще не созданы, сначала происходит объявление всех необходимых объектов и функций, а отдельная финальная функция управляет их запуском, около того:

// файл
window.BUBU = {
  say: function(str) {
    alert(str);
    
    MOO.say("moo");
  },
};

// другой файл
window.MOO = {  // Если здесь объявить const MOO вместо window,
                // из BUBU он не будет виден, выдаст ошибку.
  i: 0,
  say: function(str) {
    alert(str);
    
    if (this.i++ < 4) BUBU.say("bubu");
  },
};

//***
BUBU.say("Начали!");

Такой подход как минимум работает, пока таких объектов - 10-20, для пары десятка тысяч строк кода. С бОльшими объемами не работал - не знаю)

→ Ссылка