Since I've dealt in the past with javascript's funky "object model", I assume there is no such thing as a destructor. My searches were mildly unsuccessful, so you guys are my last hope. How do you execute stuff upon instance destruction?
-
9Your use of the pejorative isn't going to get you very far here. There's nothing "funky" about JavaScript's "object model" (which should NOT be in quotes). Just because it's not what you're used to (probably "classical OO"), doesn't mean there's anything wrong with it. – Ethan Brown Mar 21 '14 at 18:07
-
There is not concept like that in javascript, what do you want to exactly achieve with that? – ncubica Mar 21 '14 at 18:08
-
39@EthanBrown quite some attitude you got there sir. Has it occurred to you that I may not necessarily mean that it's **wrong** by adding those quotes, rather than it's **not quite what we're used to** as nearly all other languages which have introduced object model have stuck to? – php_nub_qq Mar 21 '14 at 18:10
-
@ncubica I have an interval going on in an object, which I need to destroy in case the object is no longer referable ( deleted ) – php_nub_qq Mar 21 '14 at 18:12
-
Guys, see this link http://stackoverflow.com/questions/10112670/when-are-javascript-objects-destroyed#10112776 and Steve's answer – Amit Joki Mar 21 '14 at 18:13
-
2@php_nub_qq I suggest you ask a new question relating to that specific problem, which seems like it could get you more valuable insight into both how JS works and how your specific design might be done in a better way. – Marcus Stade Mar 21 '14 at 18:17
-
@macke thank you for the suggestion, I'll just delete this one as it just seems like one big mess! – php_nub_qq Mar 21 '14 at 18:19
-
Major necromancer here but since the accepted answer was that i aint possible, I decided to share my fix to this problem.Whenever I want to destroy an object I use try catch finally and execute the destructor on the finally phase. – pihh-rocks Apr 12 '17 at 08:15
-
Another alternative is to use the "loaner" design pattern which will look something similar to the `with` context manager in Python. See here https://pastebin.com/nuJvD0zR since I'm unable to post an answer b.c. the question is marked as a duplicate. If you're using a particular framework, there may be lifecycle hooks that offer a better solution such as, for example, Angular2 offers the ngOnDestroy() hook to detach listeners. – solstice333 May 16 '17 at 23:10
-
I would like to answer this question, but it's closed, and its duplicate is not equivalent. – Andrew May 17 '20 at 21:35
-
1@Andrew you can now answer it. – php_nub_qq May 18 '20 at 18:04
4 Answers
MDN is a nice resource for JS. No, there is nothing like calling a function when an object ceases.
- 5,455
- 2
- 29
- 42
-
1Thank you for clearing that out. Just as another quick question, is there any way I could destroy an instance from within the object? Like for example `delete this;`, which makes sense, but obviously doesn't work? – php_nub_qq Mar 21 '14 at 18:18
-
2Quick answer: No. not really. With a trick: o={ kill:function(){ window.o=null;} } – Thomas Junk Mar 21 '14 at 18:22
-
13Not all environments have a `window` variable, not every variable is global (ideally none is!) and there can be dozens of other references to that object. So the "trick" is basically useless. – a better oliver Oct 22 '15 at 12:31
-
54@ThomasJunk, Re "*Since JS is garbage collected so*".. Rubbish. **Java is garbage collected too and it offers destructors.** – Pacerier Mar 22 '17 at 23:51
-
-
5@ThomasJunk Swift is garbage collected too and it offers destructors. Neither C/C++ explicitly call a ```destructor```, nor swift. C++ call destructor when object goes out the scope.```destructor``` isn't deallocator, it's just do some clean up work and leave it to the language runtime. Swift maintaining reference count. Mostly garbage collection triggered on scope out too. Garbage collection is not the reason. It's just design problem. – AntiMoron May 18 '17 at 03:29
-
1Likewise C# is also has Garbage Collection and Destructors (& Dispose & Finalize!). Destructors are not just for freeing memory and other resources. For example, it would be useful (to me today) as a good place to adjust my internal storage "map" of displayed text lines when a particular input has completed for either of 2 reasons. – Zeek2 Oct 05 '17 at 07:36
-
3@AntiMoron Minor clarification, Swift is not garbage collected (at least not in the traditional sense). ARC does not have a process running in the background that collects objects when there is memory pressure or on a periodic bases as you get with Java, JavaScript and other GC based languages. Instead with ARC enabled Swift/Objective-C when an object reference is equal to zero the object is destroyed on the spot (aka the compiler inserts retain/release for you). – James Jones Feb 05 '18 at 23:53
-
4But wouldn't be easily implementable and useful to have a callback when an object reaches zero references? – tru7 Mar 06 '18 at 10:15
-
@AntiMoron, what you say about C++ isn't entirely correct. Stack-based objects (not allocated with new) have the destructor called when they go out of scope (which is ALSO when their memory is freed). Heap-based objects (allocated with new) have the destructor called when they are deleted. Which is also associated with freeing their memory and has nothing to do with the scope. It is more accurate to say that C++ destructors are called at the point the memory is freed for the class. – stuckj Jan 04 '21 at 21:31
-
1@Pacerier, I assume you mean Java's `finalize` method. It is SIMILAR to a C++ destructor in that it's called just before the memory for the object is freed. But, unlike C++ there are no hard guarantees that `finalize` will be called. E.g., if the program exits before the next GC cycle after an object reaches a zero reference count it will never have `finalize` called. Also, if the reference count never goes to zero, but I guess you'd kinda expect it wouldn't be called in that case. :) – stuckj Jan 04 '21 at 21:38
As of more recently, this link is of more use to answer this question. The most important part:
As of 2012, all modern browsers ship a mark-and-sweep garbage-collector.
...
Cycles are no longer a problem
In the first example above, after the function call returns, the two objects are no longer referenced by any resource that is reachable from the global object. Consequently, they will be found unreachable by the garbage collector and have their allocated memory reclaimed.
Limitation: Releasing memory manually
There are times when it would be convenient to manually decide when and what memory is released. In order to release the memory of an object, it needs to be made explicitly unreachable.
So as far as cyclic references goes, de[con]structors aren't really needed.
One cool trick I have thought of though, if you have cyclic references and you want easy manual control over deconstruction...
class Container {
constructor() {
this.thisRef = [ this ];
this.containee = new Containee({ containerRef: this.thisRef });
}
//Note: deconstructor is not an actual JS thing/keyword.
deconstructor() {
//Have to delete `this.thisRef[0]` and not `this.thisRef`, in
//order to ensure Containee's reference to Container is removed.
delete this.thisRef[0];
}
doSomething() {
}
}
class Containee {
constructor({ containerRef }) {
//Assumption here is, if the Container is destroyed, so will the Containee be
//destroyed. No need to delete containerRef, no need for a
//deconstructor function!
this.containerRef = containerRef;
}
someFunc() {
this.containerRef[0].doSomething();
}
}
let c = new Container();
...
//No cyclic references!
c.deconstructor();
So here, instead of the Containee class storing a direct reference to the Container instance, it stores a reference to a size 1 array containing the Container reference, which the Container instance itself can then delete itself from. The array, with the reference, is managed by Container.
But again, this isn't really needed, since garbage collection in all modern browsers is mark-and-sweep and can handle cyclic references.
- 4,757
- 1
- 43
- 62
FinalizationRegistry might be what you need. It is not a destructor, but it executes a function once the object is garbage collected. In any case, this is what I wish I had find when I first came on here :)
- 158,107
- 27
- 234
- 292
- 123
- 1
- 5
In other languages the destructor is handy for implementing the memento pattern. That's actually what lead me to this topic. For example, in a click event it'd be nice to have a generic function that I can pass the event target to that disables the target and then re-enables it when it falls out of scope. Consider a submit button that does something like this:
function async saveMyStuff(e) {
const sleeper = new nap(e)
let data = await fetch(...)
// a bunch more code.
}
class nap {
constructor(e) {
this.button = e.currentTarget
this.button.disabled = true
}
destructor() { this.button.enabled = true }
}
This kind of construct would give me a oneliner that handles enabling/disabling all of my buttons when I'm talking to the backend or doing any other processing. I don't have to worry about cleaning up if I return somewhere in the middle or anything like that.
- 5,131
- 1
- 15
- 37