From 7aa8fa867599f89e594e48dbedf5e1f0737981b9 Mon Sep 17 00:00:00 2001 From: Shaban-Eissa Date: Thu, 30 May 2024 21:55:46 +0300 Subject: [PATCH] feat: simple store for DOM element --- 17.create-a-simple-store-for-DOM-element.md | 118 ++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 17.create-a-simple-store-for-DOM-element.md diff --git a/17.create-a-simple-store-for-DOM-element.md b/17.create-a-simple-store-for-DOM-element.md new file mode 100644 index 0000000..dfe73b3 --- /dev/null +++ b/17.create-a-simple-store-for-DOM-element.md @@ -0,0 +1,118 @@ +# 17. create a simple store for DOM element + +### Problem + +https://bigfrontend.dev/problem/create-a-simple-store-for-DOM-node + +# + +### Problem Description + +We have `Map` in es6, so we could use any data as key, such as DOM element. + +```js +const map = new Map(); +map.set(domNode, somedata); +``` + +What if we need to support old JavaScript env like es5, how would you create your own Node Store as above? + +You are asked to implement a Node Store, which supports DOM element as key. + +```js +class NodeStore { + set(node, value) {} + + get(node) {} + + has(node) {} +} +``` + +**note** + +`Map` is disabled when judging your code, it is against the goal of practicing. + +You can create a simple general `Map` polyfill. Or since you are asked to support specially for DOM element, what is special about DOM element? + +What is the Time / Space cost of your solution? + +# + +### Solution + +```js +class NodeStore { + constructor() { + this.nodes = {}; + } + /** + * @param {Node} node + * @param {any} value + */ + set(node, value) { + node.__id__ = Symbol(); + this.nodes[node.__id__] = value; + } + /** + * @param {Node} node + * @return {any} + */ + get(node) { + return this.nodes[node.__id__]; + } + + /** + * @param {Node} node + * @return {Boolean} + */ + has(node) { + // coerce to boolean value + return !!this.nodes[node.__id__]; + } +} +``` + + +# + +### Usage + +```js +const store = new NodeStore(); + +const Node = function () {}; +const node1 = new Node(); +const node2 = new Node(); + +store.set(node1, "foo"); +store.set(node2, "bar"); + +console.log(store.get(node1)); // 'foo' +console.log(store.get(node2)); // 'bar' + +console.log(store.has(node1)); // true +console.log(store.has(node2)); // true +console.log(store.has(new Node())); // false +``` + +# + +### Explanation + +Let's break down the `NodeStore` class and its usage: + +1. **Class Definition**: The `NodeStore` class is defined with a constructor and three methods: `set`, `get`, and `has`. + +2. **Constructor**: The constructor initializes an empty object `this.nodes` that will be used to store nodes. + +3. **`set` Method**: This method takes a `node` and a `value` as parameters. It assigns a unique identifier to the `node` using `Symbol()` and then stores the `value` in `this.nodes` using the unique identifier as the key. + +4. **`get` Method**: This method takes a `node` as a parameter and returns the value associated with the `node` from `this.nodes`. + +5. **`has` Method**: This method takes a `node` as a parameter and checks if `this.nodes` has a value for the `node`. It returns a boolean value. + +6. **Usage**: The usage example shows how to use the `NodeStore` class. It creates a new `NodeStore` instance and two new `Node` instances. It uses the `set` method to store values for the nodes, the `get` method to retrieve the stored values, and the `has` method to check if values are stored for the nodes. + +This `NodeStore` class provides a way to associate values with nodes in a way that doesn't mutate the nodes themselves (except for adding a unique identifier). This can be useful in situations where you need to store metadata about nodes, for example in a graph or tree data structure. +