有人问我关于在ES5和ES6中建立商店的问题。
我一直在尝试解决此问题,但是我在如何存储节点上陷入了困境
实施商店类别:
使用set(Node,value),get(Node)和 has(Node)方法,用于存储具有相应值的给定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中的Map一样工作。如果要在ES5中实现,该如何首先存储DOM节点?
答案 0 :(得分:4)
在ES5时代,通常创建一个键数组并通过线性搜索找到它们。这不是最有效的解决方案,但很简单。
InnoDb
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))
此解决方案有两个问题:首先是缓慢的线性搜索,其次,更重要的是,由于商店保留了对关键对象的引用,因此一旦销毁它们就无法进行垃圾回收。
一种更有效的选择是将密钥本身插入值中,但是实现起来要困难得多。
对于ES6部分,有一个专用的内置对象,称为WeakMap
。
答案 1 :(得分:0)
如果节点是可变的,我们可以尝试为每个节点创建并为其分配唯一的ID:
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
,我们可以在节点本身上写入唯一ID。
另一件事是,在同一页面上有多个商店的情况下,我们可能会发生ID冲突,其中每个商店可能会在同一节点上更改相同的属性。为了解决这个问题,我们可以为商店 salt 的当前实例添加一些唯一的属性,例如可以通过构造函数将其传递,然后将其前缀或后缀uniqueId
答案 2 :(得分:-2)
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
}
答案 3 :(得分:-3)
将其像对象中一样存储在可能适合您的情况的对象中。
第一个this.store
将
this.store = {}
然后,在设置功能中可以执行
this.store[node] = value;
在您的帮助下,
return this.store[node]
我认为这非常简单直接
更新: 如果您想使用DOM,请使用key:对DOM进行字符串化处理,然后将其作为键并根据需要存储值。