I'm reading up on JavaScript's virtual getter using Mozilla's documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
In it there's a section with some example code:
In the following example, the object has a getter as its own property. On getting the property, the property is removed from the object and re-added, but implicitly as a data property this time. Finally, the value gets returned.
get notifier() { delete this.notifier; return this.notifier = document.getElementById('bookmarked-notification-anchor'); },
This example comes right after the article talks about lazy/smart/memoized, but I am not seeing how the code is an example of a lazy/smart/memoized getter.
Or is that section talking about something else completely?
It just feels like I'm not following the flow of the article and it might be because I do not understand some key concept.
Please let me know if I'm just over-thinking this and that section was just shoehorned in or if the section really does relate to lazy/smart/memoized somehow.
Thank you for your guidance
Update 1:
I guess maybe I don't know how to verify that the code is getting memoized.
I tried to run this in the IDE on the page:
const obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
get notifier() {
delete this.notifier;
return this.notifier = document.getElementById('bookmarked-notification-anchor');
},
};
console.log(obj.latest);
// expected output: "c"
console.log(obj.notifier); // returns null
This seems more appropriate, but I can't verify that the cache is being used:
const obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
get notifier() {
delete this.notifier;
return this.notifier = this.log;
},
};
console.log(obj.latest);
// expected output: "c"
console.log(obj.notifier); // Array ["a", "b", "c"]
console.log(obj.notifier); // Array ["a", "b", "c"]
I guess I'm not sure why does the property need to be deleted first, delete this.notifier;
? Wouldn't that invalidate the cache each time?
Update 2: @Bergi, thanks for the suggested modifications to the example code.
I ran this (with the delete
):
const obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
get notifier() {
delete this.notifier;
return this.notifier = console.log("heavy computation");
},
};
console.log(obj.latest);
// expected output: "c"
obj.notifier;
obj.notifier;
and got:
> "c"
> "heavy computation"
I ran this (without the delete
):
const obj = {
log: ['a', 'b', 'c'],
get latest() {
if (this.log.length === 0) {
return undefined;
}
return this.log[this.log.length - 1];
},
get notifier() {
//delete this.notifier;
return this.notifier = console.log("heavy computation");
},
};
console.log(obj.latest);
// expected output: "c"
obj.notifier;
obj.notifier;
and got:
> "c"
> "heavy computation"
> "heavy computation"
So that definitely, proves memoization is happening. Maybe there's too much copying and pasting updates to the post, but I'm having a hard time understanding why the delete
is necessary to memoize. My scattered and naive brain is thinking that the code should memoize when there is no delete
.
Sorry, I'll need to sit and think about it some. Unless you have a quick tip on how to understand what's going on.
Thank you again for all of your help
Update 3:
I guess I'm still missing something.
From Ruby, I understand memoization as:
if it exists/pre-calculated, then use it; if it does not exist, then calculate it
something along the lines of:
this.property = this.property || this.calc()
With the delete
in the example code snippet, wouldn't the property always not exist and, hence, would always need to be recalculated?
There's definitely something wrong with my logic, but I am not seeing it. I guess maybe it's a "I don't know what I don't know" scenario.