15

There are six primitive data types in JavaScript:

Boolean, Number, String, Symbol, undefined, null

A WeakMap can't have primitive data types as keys. And a WeakSet can't have primitive values.

Why is this? Is it a language design decision (in which case, what drove this?) or is there a fundamental reason why primitives can't be stored weakly? I feel like it's probably the latter but I'm not sure why.

1
  • A WeakMap doesn't create a strong reference to its keys. What does it mean to not create a strong reference to a number?
    – user253751
    Mar 31, 2023 at 14:00

3 Answers 3

8

Because implementations of the language are likely to use primitive types as value types rather than reference types. That is, when you assign a value to a new variable, rather than changing the variable such that a contains a reference to the same object used in the source expression, it might copy the value of that object into the variable (if you know C#, think about the different between a struct and a class). Such a value therefore could not sensibly be used as part of a weak referenced storage system, as there is no object to be garbage collected (just values that get copied around) and therefore the weak key removal would never trigger.

The use of values rather than references for these common data types is an optimisation that can produce substantial performance improvements, and therefore the developers of ECMAscript would have been careful to avoid adding any features that mean it couldn't be used.

If you need to use such an item, you can simply create a container object (usually called a "box") to keep the value and allow it to be used in contexts where only references are permitted.

7

Background: I found this question when I assumed that WeakMap could store primitive data types, but was intrigued/confused as to how that would work. So this answer is something of a "proof by contradiction"…

The point of WeakMap is that it only keeps an entry while its key is "alive". This is relatively easy to define for real objects: if there are any references to an object — n.b. usage as a key in a WeakMap does not count as a reference! — then that object is "alive".

How would this work for primitive types? The number 1 doesn't really cease to exist if there are no "references" to it; but on the other hand even with code like

let a = 1;
let b = 1;
let c = a;

neither a nor b nor c "reference" that number anyway! What makes a primitive type primitive is that any possible value of that type has no independent existence, they are all just potential values of a variable/property. Potential states of a variable like null/true/false are similar to numbers like 1 or 42, and even strings follow the same rules. [Let's ignore symbol type….] While a JavaScript engine might optimize internally, ES2015 as a language doesn't really have a mechanism for saying whether a state like "abc" is "alive" or not.

If you were to store an entry of "abc" → "DEF" in a WeakMap, how long would you expect it to live? With objects, once an object goes "out of scope" there's no way to bring it back. But with primitives you end up with a situation where you can always re-create "abc" in a call like:

let someWeakMap = new WeakMap();
(function () {
  let key = "abc",
      value = "DEF";
  someWeakMap.set(key, value);
})();

setInterval(() => {
  let revivedKey = "abc",
      storedValue = someWeakMap.get(revivedKey);
  console.log("Does it remember?");
  console.log(storedValue === "DEF");
}, 1e3);

but who's to say how long the WeakMap should remember the stored value?

0

Values of WeakSets must be garbage-collectable. Most primitive data types can be arbitrarily created and don't have a lifetime, so they cannot be stored. Objects and non-registered symbols can be stored because they are garbage-collectable.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet#description

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.