Can someone explain why they didn’t go with (anonymous) class destructors? Or something other than a Symbol as special object key. Especially when there are two Symbols (different one for asynchronous) which makes it a leaky abstraction, no?
Destructors require deterministic cleanup, which advanced GCs can't do (and really don't want to either from an efficiency perspective). Languages with advanced GCs have "finalizers" called during collection which are thus extremely unreliable (and full of subtle footguns), and are normally only used as a last resort solution for native resources (FFI wrappers).
Hence many either had or ended up growing means of lexical (scope-based) resource cleanup whether,
- HoF-based (smalltalk, haskell, ruby)
- dedicated scope / value hook (python[1], C#, Java)
- callback registration (go, swift)
[1]: Python originally used destructors thanks to a refcounting GC, but the combination of alternate non-refcounted implementations, refcount cycles, and resources like locks not having guards (and not wanting to add those with no clear utility) led to the introduction of context managers
Destructors I other languages are typically used for when the object is garbage collected. That has a whole bunch of associated issues, which is why the pattern is often avoided these days.
The dispose methods on the other hand are called when the variable goes out of scope, which is much more predictable. You can rely on for example a file being closed ot a lock released before your method returns.
JavaScript is already explicit about what is synchronous versus asynchronous everywhere else, and this is no exception. Your method needs to wait for disposing to complete, so if disposing is asynchronous, your method must be asynchronous as well. It does get a bit annoying though that you end up with a double await, as in `await using a = await b()` if you're not used to that syntax.
As for using symbols - that's the same as other functionality added over time, such as iterator. It gives a nice way for the support to be added in a backwards-compatible way. And it's mostly only library authors dealing with the symbols - a typical app developer never has to touch it directly.
For garbage collected languages destructors cannot be called synchronously in most cases because the VM must make sure that the object is inaccessible first. So it will not work very deterministically, and also will expose the JS VM internals. For that JS already has WeakRef and FinalizationRegistry.
masklinn|9 months ago
Hence many either had or ended up growing means of lexical (scope-based) resource cleanup whether,
- HoF-based (smalltalk, haskell, ruby)
- dedicated scope / value hook (python[1], C#, Java)
- callback registration (go, swift)
[1]: Python originally used destructors thanks to a refcounting GC, but the combination of alternate non-refcounted implementations, refcount cycles, and resources like locks not having guards (and not wanting to add those with no clear utility) led to the introduction of context managers
nh2|9 months ago
matharmin|9 months ago
The dispose methods on the other hand are called when the variable goes out of scope, which is much more predictable. You can rely on for example a file being closed ot a lock released before your method returns.
JavaScript is already explicit about what is synchronous versus asynchronous everywhere else, and this is no exception. Your method needs to wait for disposing to complete, so if disposing is asynchronous, your method must be asynchronous as well. It does get a bit annoying though that you end up with a double await, as in `await using a = await b()` if you're not used to that syntax.
As for using symbols - that's the same as other functionality added over time, such as iterator. It gives a nice way for the support to be added in a backwards-compatible way. And it's mostly only library authors dealing with the symbols - a typical app developer never has to touch it directly.
senfiaj|9 months ago
https://waspdev.com/articles/2025-04-09/features-that-every-... https://waspdev.com/articles/2025-04-09/features-that-every-...
But even Mozilla doesn't recommend to use them because they're quite unpredictable and might work differently in different engines.
Garlef|9 months ago
pwdisswordfishz|9 months ago
feverzsj|9 months ago