Реализация функции хранилища Node в JavaScript - PullRequest
2 голосов
/ 12 апреля 2019

Мне задали этот вопрос по реализации магазина в ES5 и ES6.

Я пытался решить эту проблему, но застрял на том, как сохранить узел

РеализацияКласс хранения:

Реализация класса хранения с методами set (Node, value), get (Node) и has (Node), в которых хранятся данные узлы с соответствующими значениями.

Это то, что мне удалось написать (псевдокод)

function Store () {
    this.store = [];
}

Store.prototype.set = function(node, v) {
    // Problem here would be how do I store the node?
}

Store.prototype.get = function(node) {
    if(this.has(node)) {
        return this.store.find(each => {
            // Check to see if it's the same node and return.
        })
    }
}

Store.prototype.has = function(node) {
    return this.store.indexOf(node) > -1;
}

ПРИМЕЧАНИЕ. МЫ могли хранить HTML DOM в магазине.Таким образом, ключом будет элемент "DOM", а не строка.

Может кто-нибудь просветить меня примером?Я бы предположил, что это будет работать как карта в ES6.Как мне сохранить узел DOM, если бы я реализовал это в ES5?

Ответы [ 4 ]

4 голосов
/ 12 апреля 2019

В дни ES5 было принято создавать массив ключей и определять их местоположение с помощью линейного поиска.Это не самое эффективное решение, но простое.

function Store() {
    this.keys = [];
    this.values = [];
}

Store.prototype.set = function(key, val) {
    var i = this.keys.indexOf(key);
    if(i < 0) {
        i = this.keys.push(key) - 1;
    }
    this.values[i] = val;
};

Store.prototype.get = function(key) {
    return this.values[this.keys.indexOf(key)];
};

Store.prototype.has = function(key) {
    return this.keys.indexOf(key) >= 0;
};

//

a = document.querySelector("#a")
b = document.querySelector("#b")
c = document.querySelector("#c")

s = new Store()

s.set(a, '1')
s.set(b, '2')

console.log(s.has(a), s.get(a))
console.log(s.has(b), s.get(b))
console.log(s.has(c), s.get(c))
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>

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

Более эффективный вариант - вводить ключ в сами значения, но это гораздо сложнее реализовать.

Для части ES6 есть специальная встроеннаяобъект для такого рода вещей, называется WeakMap.

0 голосов
/ 30 июня 2019

Если узлы изменчивы, мы можем попытаться создать и назначить каждому узлу его уникальный идентификатор:

function NodeStore() {
  this.nodesValueMap = {};
  this.lastId = 0;
}

NodeStore.prototype.set = function(node, value) {
  // text nodes do not have dataset (DOMStringMap), create simple object
  node.dataset = node.dataset || {};
  node.dataset.uniqueId = node.dataset.uniqueId || ++this.lastId;
  this.nodesValueMap[node.dataset.uniqueId] = value;
}

NodeStore.prototype.get = function(node) {
  return node.dataset.uniqueId && this.nodesValueMap[node.dataset.uniqueId];
}

NodeStore.prototype.has = function(node) {
  return !!(node.dataset.uniqueId && this.nodesValueMap[node.dataset.uniqueId]);
}

var textNode = document.querySelector("#a").childNodes[0];
var b = document.querySelector("#b");
var c = document.querySelector("#c");

var store = new NodeStore();

store.set(textNode, '1');
store.set(b, '2');

console.log(store.has(textNode), store.get(textNode));
console.log(store.has(b), store.get(b));
console.log(store.has(c), store.get(c));
<div id="a">asdf</div>
<div id="b"></div>
<div id="c"></div>

теперь все методы будут выполняться со сложностью O (1).

Нет необходимости использовать dataset, мы могли бы написать уникальный идентификатор на самом узле.

Другое дело, что у нас могут быть коллизии идентификаторов в случае нескольких хранилищ на одной странице, где каждое хранилище может изменять одно и то же свойство в одном и том же узле. Чтобы решить эту проблему, мы могли бы добавить некоторые уникальные для текущего экземпляра хранилища salt , которые можно было бы передать, например, через конструктор, а затем использовать в качестве префикса или суффикса uniqueId.

0 голосов
/ 12 апреля 2019

Храните его как объекты внутри объектов, которые могут работать для вашего случая.

Сначала this.store будет

this.store = {}

Затем в функции набора вы можете выполнить

this.store[node] = value;

и в вашем распоряжении

return this.store[node]

Это довольно просто и понятно.

Обновление : если вы хотите, чтобы DOM имелключ: Stringify DOM и принять его в качестве ключа и сохранить значение, как вы хотите.

0 голосов
/ 12 апреля 2019
function Store () {
    this.store = {};
}

Store.prototype.set = function(node, v) {
    this.store[node] = v;
}

Store.prototype.get = function(node) {
    return this.store[node];
}

Store.prototype.has = function(node) {
    return this.store[node] !== undefined
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...