I'm attempting to create something of a tree structure.
I wish to access my data as follows:
data[key1][key2]
However, key1 and key2 have a symmetric relationship; the following is always true:
data[key1][key2] == data[key2][key1]
More specifically, I have data[key1][key2]
and data[key2][key1]
pointing to the same object, such that changes to one affect the other.
My problem arises because I wish to delete the underlying object. I know if I use:
delete data[key1][key2];
data[key2][key1]
still refers to the object.
My question is this: is there any way to remove the underlying object, or overwrite it with something falsey, such that both properties above will evaluate falsey?
In JavaScript, objects and arrays are mutable by default, but primitive values are not — once a primitive value is created, it cannot be changed, although the variable that holds it may be reassigned.
Immutable data cannot change its structure or the data in it. It's setting a value on a variable that cannot change, making that value a fact, or sort of like a source of truth — the same way a princess kisses a frog hoping it will turn into a handsome prince.
Update on 12 Aug 2021. Happily, the creator of Immutable JS resumed to maintaining his lib, and commits are regular now.
Think of it like this:
data[key1][key2] -----> object1
^
data[key2][key1] ---------+
If you change the key for one of them (say the latter) to a new object you'll just get this:
data[key1][key2] -----> object1
data[key2][key1] -----------> object2
(Or the key will simply be missing if you delete it:)
data[key1][key2] -----> object1
data[key2]
That is, you'll change one of the references but not the other. Any attempt to replace only one of them will accomplish this. You have two options:
a) Change both keys to point to the new object:
data[key1][key2] -----> object2
^
data[key2][key1] ---------+
(Or delete both keys:)
data[key1][key2] object1 (no references, will be garbage collected)
data[key2][key1]
b) Modify a field on the object itself. This way they'll both still be pointing to the same object, but something about it will be different. Any code that you use will have to take this into account, though.
data[key1][key2] -----> object1 with 'isDeleted'=true
^
data[key2][key1] ---------+
The a) option seems to make the most sense given your use case. If you have both keys anyway, why not update/delete both?
The valueOf() method might offer a solution. If you're doing an explicit comparison to a boolean value, valueOf will be called as part of the type-casting to Boolean. For example, let's say your data structure references some object, x
...
> x = {}
Object
> (x == false ? 'yes' : 'no')
"no"
> x.valueOf = function() {return false;}
function () {return false;}
> (x == false ? 'yes' : 'no')
"yes"
... i.e. if data[key1][key2] == data[key2][key1] == x
, then assigning x.valueOf = function() {return false;}
will change what x
evaluates to when explicitely caste to a boolean. So as long as you're testing for data[key1][key2] == false
, x
should appear to be falsy.
However, you need to be careful with this because x
is less falsy than a primitive value. E.g. Even after assigning valueOf as above, implicit coercions still appear to be truthy ...
(x ? 'yes' : 'no')
"yes"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With