let person = { id: 123, name: "Mohit" }; const wk = new WeakSet(); wk.add(person); person = null; console.log(wk.has(person)); console.log(wk); When I logged these two lines, the first returned false, as expected. But when I logged the wk WeakSet, it still had a value property which held the underlying object used in my code by person, i.e. { id: 123, name: "Mohit" }. Why did this happen?
Only watched the Set section, but the code doesn't seem convicing 🤔After you set `son=null` then the check becomes `kids.has(null) // returns false;` That is kind of expected, wouldn't it make more sense to check for `kids.size` ? Show that by removing the ref we lost an element in the set without calling delete directly.
You don't have the concept yet. WeakSet has no size method. So, you cannot do that. son is a strong reference to the value { name: 'Alex' } in memory. We then add son as an item inside the WeakSet kids. When the variable son is changed from { name: 'Alex' } to null, that means that son no longer has any connection to that { name: 'Alex' } value. Because son was the only strong reference to { name: 'Alex' } the value { name: 'Alex' } can be garbage collected because there are no more strong references to it. The WeakSet will lose { name: 'Alex' } from it's list automatically because the value is gone from memory. The WeakSet doesn't care about "son". It was watching { name: 'Alex' } in memory. When that disappears from memory, the weakSet loses that entry. WeakSets can't loop through the values. They can't check their size. This is because the values it holds can disappear at any point. The WeakSet does not prevent the garbage collection of any value.
@@SteveGriffith-Prof3ssorSt3v3 I think the first part of the argument is still valid. When you say `son = null`, you set son explicitly to null, so you no longer try to access the original object the son variable referenced, but the `null`. If you write `kids.has(son)` after you set `son = null`, it will just be evaluated as `kids.has(null)` which will be false anyway. I'm not sure, please correct me if I'm wrong, but I assume as long as you can reference any value, it is still in memory, so you cannot showcase how it will disappear from the weakmap. If you could keep the reference to call `.has()` with it, it wouldn't be garbage collected so weakmap would still have the value. But when the value gets garbage collected, it means it no longer has any references, so you don't have anything to call `.has()` with. The importance of a weakmap is that if you have no other references, only the weakmap, it won't stop the value from being garbage collected, so it won't cause a memory leak.
I guess you are right. I wrote a simple example with console log and a timeout function. The weakMap still holds a reference, even when on of the objects is already gone. let user1 = {name: 'Sheridan'}; let user2 = {name: 'Mollari'}; let user3 = {name: 'Ivanova'}; const weakMapTest = new WeakMap(); weakMapTest.set(user1, 'green'); weakMapTest.set(user2, 'green'); weakMapTest.set(user3, 'green and purple'); console.log({weakMapTest}); user1 = null; setTimeout(() => { console.log({weakMapTest}); }, 10_000); In Firefox there is an tool for manually triggering the GC. Just open FF and enter about:memory Here you can see the loose reference. Without triggering the GC the values stay inside the weak map. After hitting GC, the {name: 'Sheridan'} object is gone.
@@tvili999 You are right. There is no way to directly test if a value in a WeakSet has been garbage collected. An object might get garbage collected when it becomes unreachable, which means there are no references to it. You could indirectly check if the value has been garbage collected: let son = { name: 'Alex' }; const daughter = { name: 'Bree' } const weakSon = new WeakRef(son); // Create a weak reference to the son object const kids = new WeakSet(); kids.add(son); kids.add(daughter); son = null; // No more strong references to the previous value of son const interval = setInterval(() => { if (!kids.has(weakSon.deref())) { console.log('Son has been garbage collected'); return clearInterval(interval); } console.log('Waiting for garbage collection...'); for (let i = 0; i < 10; i++) { // Allocate memory to trigger garbage collection const largeObj = new Array(1000000).fill('x'); kids.add(largeObj); } }, 1000);
Thank you sir for this tutorial! But you haven't explained where and why one should/could use them if there is no looping available? In what cases would one want to put these references in a container? I hope my question is understandable. Thanks again.
I did explain why. I didn't give practical code samples of Weak references being applied. This is not something that a junior developer would ever use or need to use. They are more a thing that when you need them you will understand why. WeakSets and WeakMaps are more of an advanced tool for improved garbage collection. When you need to have a centralized storage location for items that allows you to check for existence of items. You can have references elsewhere in your code that you are using in your interface. The Weak container could use the interface elements as the keys. You can check with the Weak container to see if the elements still exist in the interface or are referenced from the interface. As strong references are cleared away the objects in the Weak container would also be removed by garbage collection. For less experienced developers the important key here is understanding Reachability and the difference between Weak and Strong references. There is no situation where you MUST use the Weak Collections.
i don't understand what are you trying to say let s=new Set() let a={b:"something"}; s.add(a); a=null; console.log("a is present "+s.has(a)); a={b:"something"}; s=new WeakSet() s.add(a); a=null; console.log("a is present "+s.has(a)); both are giving same answer
In your Set example we set a = null. At that point the Set still contains a reference {b: "something"}. If you console the Set you will see it there. The variable a now holds null. The Set does not contain null. With the WeakSet once a is set to null, The WeakSet is no longer allowed to hold the {b:"something"}. It will be empty
@@SteveGriffith-Prof3ssorSt3v3 let s=new Set() let a={b:"something"}; s.add(a); a=null; console.log(s); a={b:"something"}; s=new WeakSet() s.add(a); a=null; console.log(s); I just did it and both answer have {b:"something"} why?
I hate how easy it is to create a new strong reference after getting from a weak set. I hoped weak- structures could prevent memory leaks but it's really not the case. You could use them for top level weak storage I guess...
Thank you for your detailed explanation. It was very informative and I appreciate you taking the time to explain it thoroughly.🫀 Just eager to know in what situations should we use WeakMap and WeakSet?
By far the best and clearest explanation for WeakSet and WeakMap 👍🏻 Although I can't imagine how and when I will use them effectively.
They're not an everyday thing
You made this so easy to understand thank you.
Thanks for the video, very clear explanation!
let person = { id: 123, name: "Mohit" };
const wk = new WeakSet();
wk.add(person);
person = null;
console.log(wk.has(person));
console.log(wk);
When I logged these two lines, the first returned false, as expected. But when I logged the wk WeakSet, it still had a value property which held the underlying object used in my code by person, i.e. { id: 123, name: "Mohit" }.
Why did this happen?
this is amazing thank you Steve!
Thank you for the great video! 🙏
for Map -- keys don't have to be Objects. They can be any primitives as well. For WeakMap - keys cannot be primitive types - only reference types.
@aibulat1871 keys don't have to be objects, they are allowed to be.
Only watched the Set section, but the code doesn't seem convicing 🤔After you set `son=null` then the check becomes `kids.has(null) // returns false;` That is kind of expected, wouldn't it make more sense to check for `kids.size` ? Show that by removing the ref we lost an element in the set without calling delete directly.
You don't have the concept yet.
WeakSet has no size method. So, you cannot do that.
son is a strong reference to the value { name: 'Alex' } in memory.
We then add son as an item inside the WeakSet kids.
When the variable son is changed from { name: 'Alex' } to null, that means that son no longer has any connection to that { name: 'Alex' } value.
Because son was the only strong reference to { name: 'Alex' } the value { name: 'Alex' } can be garbage collected because there are no more strong references to it.
The WeakSet will lose { name: 'Alex' } from it's list automatically because the value is gone from memory.
The WeakSet doesn't care about "son". It was watching { name: 'Alex' } in memory.
When that disappears from memory, the weakSet loses that entry.
WeakSets can't loop through the values. They can't check their size. This is because the values it holds can disappear at any point. The WeakSet does not prevent the garbage collection of any value.
@@SteveGriffith-Prof3ssorSt3v3 I think the first part of the argument is still valid. When you say `son = null`, you set son explicitly to null, so you no longer try to access the original object the son variable referenced, but the `null`.
If you write `kids.has(son)` after you set `son = null`, it will just be evaluated as `kids.has(null)` which will be false anyway.
I'm not sure, please correct me if I'm wrong, but I assume as long as you can reference any value, it is still in memory, so you cannot showcase how it will disappear from the weakmap.
If you could keep the reference to call `.has()` with it, it wouldn't be garbage collected so weakmap would still have the value. But when the value gets garbage collected, it means it no longer has any references, so you don't have anything to call `.has()` with.
The importance of a weakmap is that if you have no other references, only the weakmap, it won't stop the value from being garbage collected, so it won't cause a memory leak.
I guess you are right. I wrote a simple example with console log and a timeout function. The weakMap still holds a reference, even when on of the objects is already gone.
let user1 = {name: 'Sheridan'};
let user2 = {name: 'Mollari'};
let user3 = {name: 'Ivanova'};
const weakMapTest = new WeakMap();
weakMapTest.set(user1, 'green');
weakMapTest.set(user2, 'green');
weakMapTest.set(user3, 'green and purple');
console.log({weakMapTest});
user1 = null;
setTimeout(() => {
console.log({weakMapTest});
}, 10_000);
In Firefox there is an tool for manually triggering the GC. Just open FF and enter about:memory
Here you can see the loose reference. Without triggering the GC the values stay inside the weak map. After hitting GC, the {name: 'Sheridan'} object is gone.
@@tvili999 You are right.
There is no way to directly test if a value in a WeakSet has been garbage collected. An object might get garbage collected when it becomes unreachable, which means there are no references to it.
You could indirectly check if the value has been garbage collected:
let son = { name: 'Alex' };
const daughter = { name: 'Bree' }
const weakSon = new WeakRef(son); // Create a weak reference to the son object
const kids = new WeakSet();
kids.add(son);
kids.add(daughter);
son = null; // No more strong references to the previous value of son
const interval = setInterval(() => {
if (!kids.has(weakSon.deref())) {
console.log('Son has been garbage collected');
return clearInterval(interval);
}
console.log('Waiting for garbage collection...');
for (let i = 0; i < 10; i++) {
// Allocate memory to trigger garbage collection
const largeObj = new Array(1000000).fill('x');
kids.add(largeObj);
}
}, 1000);
Wuhuuu, riding the edge of jS, U feel i peeps?! Maybe some neck beard C coders will finally see what the fuzz is all about xD Thx Steve!
Thank you sir for this tutorial! But you haven't explained where and why one should/could use them if there is no looping available? In what cases would one want to put these references in a container? I hope my question is understandable. Thanks again.
I did explain why. I didn't give practical code samples of Weak references being applied. This is not something that a junior developer would ever use or need to use. They are more a thing that when you need them you will understand why.
WeakSets and WeakMaps are more of an advanced tool for improved garbage collection. When you need to have a centralized storage location for items that allows you to check for existence of items. You can have references elsewhere in your code that you are using in your interface. The Weak container could use the interface elements as the keys. You can check with the Weak container to see if the elements still exist in the interface or are referenced from the interface. As strong references are cleared away the objects in the Weak container would also be removed by garbage collection.
For less experienced developers the important key here is understanding Reachability and the difference between Weak and Strong references.
There is no situation where you MUST use the Weak Collections.
@@SteveGriffith-Prof3ssorSt3v3 Okay. Thank you for explaining.
i don't understand what are you trying to say
let s=new Set()
let a={b:"something"};
s.add(a);
a=null;
console.log("a is present "+s.has(a));
a={b:"something"};
s=new WeakSet()
s.add(a);
a=null;
console.log("a is present "+s.has(a));
both are giving same answer
WeakSets are collections of objects only. They cannot contain arbitrary values of any type, as Sets can.
They both held objects _weakly_ so they are the same in that behavior.
@@agent-33 doesn't he said something else
In your Set example we set a = null. At that point the Set still contains a reference {b: "something"}. If you console the Set you will see it there.
The variable a now holds null. The Set does not contain null.
With the WeakSet once a is set to null, The WeakSet is no longer allowed to hold the {b:"something"}. It will be empty
@@SteveGriffith-Prof3ssorSt3v3
let s=new Set()
let a={b:"something"};
s.add(a);
a=null;
console.log(s);
a={b:"something"};
s=new WeakSet()
s.add(a);
a=null;
console.log(s);
I just did it and both answer have {b:"something"} why?
Thank you 🙏
May i know what font name you use?
Jet Brains Mono
I hate how easy it is to create a new strong reference after getting from a weak set. I hoped weak- structures could prevent memory leaks but it's really not the case. You could use them for top level weak storage I guess...
stupendous
it is very confusing and why to use must be cleared out, still trying to understand what is the difference normal use and this one.
Thank you for your detailed explanation. It was very informative and I appreciate you taking the time to explain it thoroughly.🫀
Just eager to know in what situations should we use WeakMap and WeakSet?