1

I was reading about lit-html and how it works here.

But i could not understand how they can use the strings argument as cache-key. I have read about Map in mdn but i didnt found anything that explains how Map get and set works.

My question how the argument strings can be used as key. Basically how Map stores keys because keys can be anything.

// Store how many times we've seen each literal
let counts = new Map();

// A template tag that updates the count storage and longs the count
let count = (strings) => {
  // The strings object is our Map key
  let c = (counts.get(strings) || 0) + 1;
  counts.set(strings, c);
  console.log(`literal ${strings.join('')} seen ${c} time(s)`);
};

// Two functions that evaluate to different tagged literals
let f = (text) => count`abc`;
let g = (text) => count`def`;

f();
f();
g();
VLAZ
  • 26,331
  • 9
  • 49
  • 67
hawks
  • 861
  • 1
  • 8
  • 20
  • A map...works. It's a generic [well known datastructure](https://en.wikipedia.org/wiki/Hash_table), so the ES6 implementation is nothing more than introducing a default built-in of this datastructure. Well, a different one than plain objects, since `{abc: 2, def: 1}` is also fundamentally a hash/map/hashmap but only slightly more limited in some ways (can't have many types for keys) but has other advantages like prototypal inheritance. However, as a data structure, they are the same. – VLAZ Jan 29 '20 at 14:17
  • That things i know about Map. But i am trying understand how it sets the key when the key is not a string or primittive value. For example, how it finds the correct key/value pair when the key is an array (`map.set([1,2,3], 'myvalue')`) – hawks Jan 29 '20 at 14:22
  • The same way you'd set it in a normal array, really. `arr = []; key = [1, 2, 3]; arr.push(key); arr.includes(key); /* true */ arr.includes([1, 2, 3]); /* false */` You get the same behaviour with maps - they still do a normal comparison via (essentially) `===` since `map.set([1,2,3], 'myvalue'); map.get([1, 2, 3])` will not return `'myvalue'`. – VLAZ Jan 29 '20 at 14:26
  • So it compares the values and the reference of the key when they are non primitive values? So, my question is when the `count` is called the `strings` argument has his own reference and how each call (of the `count` function) points to same reference?. If i understand correctly when a function is called its created new local execution context, so the argument `strings` has different refrence. Correct if im wrong please. And Thanks – hawks Jan 29 '20 at 14:47
  • All variables in JavaScript are [pass-by-value](https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language), so two strings *with the same content* are always equal: `"ab" === "a" + "b" //true`. All primitive values exhibit this behaviour...well, Symbols are different but that's by design. Objects (which includes functions and arrays) are *also* pass-by-value. However, the *value* of an object variable is its reference. So, `a = [1, 2, 3]; b = [1, 2, 3]` point to two different arrays, let's say ref `0xAAA` and ref `0xBBB`. When you do `a === b`, – VLAZ Jan 29 '20 at 15:11
  • 3
    you're actually checking if the ref `0xAAA` is equal to the ref `0xBBB`. Since they are not, they point to two different memory locations and thus two different objects, thus they are not equal. An object is therefore only equal to itself: `a = [1, 2, 3]; b = a;` would set `a` to the reference `0xAAA` and `b` will also hold `0xAAA` now (pointing at the same object). Thus `a === b` is checking if `0xAAA` is `0xAAA` and that's true. So, don't confuse how primitive values and objects are compared - *technically*, it's the same but for a different reason and a different result than you'd expect. – VLAZ Jan 29 '20 at 15:12
  • @VLAZ thanks for the clarification. Could you elaborate the last part "it's the same but for a different reason and a different result than you'd expect" please. I dont understant it. – hawks Jan 30 '20 at 08:53
  • Again, JavaScript is always pass-by-value. So you're always doing value comparison whether you compare primitives or objects, so `x === y` will do the exact same operation in either case. From a technical standpoint - the same. Yet the behaviour seems different - `"foo" === "foo"` and `["f", "o", "o"] === ["f", "o", "o"]` produce different results to what one might expect, since many assume that an object's value is the data the object (currently) holds. – VLAZ Jan 30 '20 at 09:00

0 Answers0