I'm going through Immutable.js's source code and there's an ownerID
field that I don't understand.
Here's the source for Map.asMutable()
and Map.asImmutable()
: https://github.com/facebook/immutable-js/blob/master/src/Map.js#L171
It seems like the only difference between a mutable and an immutable object are their ownerID
s. What is an ownerID
and what is it used for?
3 Answers
Answers 1
If you track back the property:
L#14:
import { DELETE, SHIFT, SIZE, MASK, NOT_SET, CHANGE_LENGTH, DID_ALTER, OwnerID, MakeRef, SetRef, arrCopy } from './TrieUtils'
in src/TrieUtils.js :
L#36:
// A function which returns a value representing an "owner" for transient writes // to tries. The return value will only ever equal itself, and will not equal // the return of any subsequent call of this function. export function OwnerID() {}
It is some property they create like hash to represent a virtual owner.
Answers 2
It is used to ensure mutability in asMutable
returned instances. When asMutable
is invoked, it ensures an __ownerId
and returns the current instance back -
asMutable() { return this.__ownerID ? this : this.__ensureOwner(new OwnerID()); }
Then any supported mutating operations return the current instance back, instead of creating a new instance with the changes (which is key for immutability).
E.g., here's how the "clear" method operates based on the presence of __ownerId
-
clear() { if (this.size === 0) { return this; } if (this.__ownerID) { this.size = 0; this._root = null; this.__hash = undefined; this.__altered = true; return this; } return emptyMap(); }
Notice that when this.__ownerID is present, the method returns the current instance (thereby mutating itself). But when it is absent, it returns a new map for ensuring immutability.
Answers 3
From the source code:
// A function which returns a value representing an "owner" for transient writes // to tries. The return value will only ever equal itself, and will not equal // the return of any subsequent call of this function. function OwnerID() {}
My understanding of the above is that the this.__ownerID
field is used to compare objects. A Map
being compared against itself will have the same ownerID
, while a Map
being compared against another Map
will see two different ownerID
s.
You can see an example of this usage a little farther down in the file in question:
__ensureOwner(ownerID) { if (ownerID === this.__ownerID) { return this; } if (!ownerID) { this.__ownerID = ownerID; this.__altered = false; return this; } return makeMap(this.size, this._root, ownerID, this.__hash); }
In fact, searching the entire repo, you'll see that this function is common across data types, with each type having a slightly modified version to return a correct new version of that type.
0 comments:
Post a Comment