Description
The Set
constructor when called with an iterable behaves as follows:
- Create a new object with the appropriate prototypes derived from NewTarget
- Look up
add
on that object - Repeatedly invoke
add
on the new object passing each member of the iterable
I believe the lookup for add
is to support subclasses overriding add
, such that
class A extends Set {
add(x) {
console.log(x);
}
}
new A([0, 1]);
But this also has the consequence that changing Set.prototype.add
changes the behavior of the Set
constructor, which adds implementation overhead. I don't think it's intended or necessary that Set.prototype.add
be monkey-patchable in this way. Perhaps we could say that if NewTarget is the Set
constructor itself (edit: from the same realm), it can just use the original Set.prototype.add
. This would preserve the subclassing behavior (i.e., my example would work the same) while reducing complexity in the common non-subclassed case.
This would debatably be an inconsistency, but it's only observable if you're patching intrinsics, which is a case where I don't think we should worry too much about trying to maintain consistency.
This all applies to WeakSet
, Map
, and WeakMap
as well.