var person = {
name: 'John'
};
function Pet1(person) {
var owner = person.name;
this.showOwner = function() {
alert(owner);
}
}
function Pet2(person) {
this.showOwner = function() {
alert(person.name);
}
}
var pets = [new Pet1(person), new Pet2(person)];
...
pets.splice(0, 1);
pets.splice(0, 1);
Which code above prevent's JS GC to not collect instances of Pet1 and Pet2 when they go out of scope or when there are no more references to either. What I know is Pet2 but don't you think Pet1 also prevents JS GC?
On the question from your comment:
will the person (it's global in this case) variable prevent instances of Pet1 and Pet2 to be garbage collected (if out of scope and no more references)
No, why should it? person does not reference the Pet instances, it's the other way round. Once you have removed the references to the Pet instances from the pets array, there is nothing that prevents the GC to collect them (assuming your "..." code does not create other references to pets[0] or pets[1]).
The answer is "it depends".
In terms of modern engines, if person were removed from everywhere else in the system, it could still be collected, even if it was mentioned in the argument, because despite being inside the closure, it's never referenced ever again, from any method which is publicly available.
Therefore, engines which support removing vestigial pieces of a scope could easily run GC on that object.
The question, then, is which engines do that, and which versions of those engines do so?
I'm not sure of the answer to that.
Just that it's possible, but could remain resident in memory on older or lesser JS engines.
EDIT
Think of it like this: var pet1 = new Pet1(person);
Pet1 used person to set values for pet1.
person doesn't know a thing about pet1.
var pet2 = new Pet2(person);
pet2 has a function which looks for person, to read a value.
So even if person is never mentioned in the code again, it can't be removed, because pet2 might call a function which needs to find person...
person still has no clue what a pet2 is.
When pet2 isn't needed anymore, and when it's removed from the array above, and when every single variable/object-property/array-index which referenced it has its references removed, including removing functions which were created inside of a scope that it exists in, and have references to it, somehow, it can be removed, because NO OTHER CODE is looking for/hanging onto pet2.
Once pet2 is gone, person isn't used anywhere else, anymore.
Therefore, person can be marked for collection.
GC is all about what has access to a thing.
If other things are still talking about the object, then the object is not allowed to be removed.
An instance could depend on 50 arguments, and have references to 120 other outside objects, but that instance could still be collected if nobody else cares about it.
Related
I have some questions about my prototypal inheritance pattern that I am using for my app. First of all take a look at the pattern that I am using;
const myObjectProto = (function() {
const proto = Object.create( parentProto );
// private variables
let title = 'Some String';
// private functions
const addEmoticon = function() {
return title + ' ';
}
proto.getTitle = function() {
return addEmoticon();
}
return proto;
})();
And when I want to use it, I will use it like below:
const firstObject = Object.create( myObjectProto );
const secondObject = Object.create( myObjectProto );
// call a public function
firstObject.getTitle();
secondObject.getTitle();
My first question is this: assume that we are creating 100 objects from its corresponding proto; As far I know title is shared among them. That means if a function change it, it will be changed for all created objects. I am a little worried about the memory in this case. Do I use memory efficient with this pattern? Can someone clarify how Object.create treats with title?
My second question is about the memory leak; Let say that we want to set the firstObject to null;
firstObject = null;
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak. Am I right? If this is true, how can I fix it?
title is a local variable. It will exist as long as some code can access it. It will only exists once, as the IIFE only executes once, thus only one variable gets created. The function inside addEmoticon can access title, in other words it closures over it. As it is a local itself, it will also only exist as long as it can be accessed. It gets accessed inside the function stored inside proto.getTitle, which again closures over addEmoticon. proto.getTitle exists as long as proto can be accessed. As the value of proto gets stored inside the global variable const myObjectProto, it can always be accessed thus it will live forever (as well as every value that can be accessed through it, e.g. title).
Do I use memory efficient with this pattern?
Well, you allocate a few bytes once. Assuming that you have a few Megabytes available, thats not a lot.
As far I know title is shared among them
Yes.
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak.
You loose the reference to the instance stored in firstObject, thus making it viable for garbagge collection. That might free a few bytes. As the prototype is still available via secondObject and myObjectProto, it will continue living.
I have memory leak. Am I right?
A memory leak is a noticible amount of memory, that is still allocated although the values in it don't need to be used anymore. Under the assumption that you want to work with secondObject, and create new instances from myObjectProto, everything you've stored is still needed. Your code is perfectly fine.
So, say I have a class (not a great example but it works for this purpose):
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
this.getInfo();
}
and I want to create an instance of it, so I would typically do:
var apple = new Apple();
However, in my scenario, because the instance will execute immediately, I don't need the variable, so I just want to do:
new Apple();
which I know is possible, but what I don't know is what javascript will do behind the scenes. Will it create a memory reference anyway? Will it put some token into global variables? Or does it just run a one time executing class instance?
essentially, I'm asking what the harm in just using "new Apple();" is.
Update
Since this is clearly too ambiguous to get the advice i was looking for let me be more specific. At my company we use a standard classing structure for javascript files simply for consistency. This is the structure i'm talking about (mind you uses the class design from http://ejohn.org/blog/simple-javascript-inheritance/):
MyClassName = Class.extend({
init: function (/*param1, param2, etc*/) {
// this method is called immediately when the class is instantiated.
},
destroy: function () {
// this is your clean up method.
}
});
There are times when MyClassName will not need to be assigned to a variable simply because the intent is for the init method to start the whole thing, so short of lint picking up the usage of "new MyClassName();" to be an error what will core Javascript do is my ultimate question.
Most JS linters will flag instantiating a class without assigning it to a variable or property, because it indicates that either:
You made a mistake, and actually need a reference, or
You're calling the constructor for its side-effects (as is the case here), in which case you'd be better off calling a function instead.
In the latter case, it is likely (though it depends on the JS environment) that you are allocating memory you won't use by instantiating an object you don't reference. It's also (though this is opinion) usually a Bad Idea to have side effects in your constructor, as they undermine developer expectations about what creating an instance will do, and they can lead to hard-to-find bugs. It's usually simpler to put the side-effect code in a method and call it:
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
}
var a = new Apple();
a.getInfo();
People have already addressed why you shouldn't so I'll say what actually happens. Since your object uses this a new memory reference will be created. Assuming you don't pass that reference to anything (i.e., store a reference to the object in another object or in a closure context) and it doesn't reference any external, persistent values (anything in a closure context that is used elsewhere) then it will be collected during the next garbage collection cycle.
This article specifically talks about V8's memory model but most Javascript engines follow a similar model.
TL;DR It's not considered good practice but assuming you don't store any references to the new object, you won't be any worse for wear.
If I do the following (in the global scope):
var myObject = {name: "Bob"};
I have a way to point to that object in memory (i.e. the string identifier "myObject)". I can open the console and type: myObject.name and the console will respond with:
"Bob"
Now, if I just type:
{name: "Jane"};
I'm creating that object somewhere and I'm guessing it goes on living in some scope. Is there any way I can find it? Does it exists under window somewhere in some generic store?
Edit: Some people are saying it will just get garbage collected.
So how about this example:
var MyObject = function(){
$("button").click(this.alert);
}
MyObject.prototype.alert = function(){
alert("I heard that!")
}
new MyObject();
It can't be garbage collected because its callback is bound to a DOM event. Where does the resulting object live and can it be accessed?
If there is no reference pointing to this object (that is you didn't assign it to any variable or to the value of any property), then there is no way to access it and in fact it's no living as the garbage collector can reclaim this memory immediately.
The short answer is no, the object isn't kept alive in memory somewhere you can't reach. Bit life is live: the truth is a bit more complicated, but not by much, if you grasp the basics.
Update:
In response to your update: you're right, in a way. The callback is a reference to MyObject.prototype.alert, which you accessed using this.alert, but that function object is being referenced by a constructors prototype, and can't be GC'ed anyway. The instance itself is not involved in the alert function itself, so it can be GC'ed safely.
Think of it like this:
MyConstructor.prototype.alert = 0x000123;//some memory address
||
\/
0x000123 = [object Function];
The function object itself isn't directly attached to anything, it floats there in memory, and is being referenced by the prototype. When you create an instance:
new MyConstructor().alert;
Is resolved as follows:
[new MyConstructor instance] allocated at e.g 0x000321
||
\\
\=>[alert] check for alert #instance -> not found
\\
\=> check prototype, yield 0x000123 <-- memory address, return this value
So upon executing the statement:
$("button").click(this.alert);
this.alert is an expression that is resolved to 0x000123. In other words, jQ's click method (function object) only receives the memory address of the alert function object. The instance, or indeed the constructor isn't involved at all. That's why this, or the call-context, can change depending on how and where a function is invoked. see here for more on ad-hoc context determination
I'll even do you one better:
/*assume your code is here*/
new MyConstructor().alert = function(){ alert('I am deaf');};
MyConstructor.prototype.alert = 'foo';
$('#button').click();
Guess what, the click event alert "I heard that" all the same, the prototype isn't even involved, let alone the instance.
If MyConstructor were to go out of scope, the click event will still work fine, because the GC still sees a reference to the alert function object that isn't out of scope yet. everything else is available for GC'ing, though...
The JS garbage collector (GC) is a flag-and-swipe GC. When the JS engine encounters your statement, it does allocate the memory required to store your object. When the next statement is reached, that object will probably still be in memory.
Every now and then, the GC X-checks all the objects it sees in memory, and tries to locate all references to that object that are still accessible. When it comes across the object literal that was just created in that statement, but no reference to was assigned, the object is flagged for garbage collection.
The next time the GC gets about its business of swiping flagged object, that object will be removed from memory.
Of course, this isn't entirely true for all engines. suppose your statement was written in an IIFE, that returned a function:
var foo = function()
{
{name: 'bar'};
return function()
{
return 'foobar';
};
}());
Some engines just keep the entire scope of the IIFE in memory, and only deallocate the memory for that scope when the return value of the IIFE goes out of scope (is flagged for GC). Other engines, like V8 last time I checked, will in fact flag those objects/vars of the outer scope that aren't referenced by its return value.
Though, come to think about it, it might not apply to this case, because the GC might even kick in even before the IIFE returns... But on the whole, that's just nit-picking.
There's also the question of logical OR's to consider:
var name = (mayNotExist || {name:'default'}).name;
In this case, if mayNotExist does exist, the object literal will never even be created, thanks to JS's short-circuit evaluation of expressions.
A couple of links on the matter:
Objects and functions in javascript
javascript - How to make this code work?
What makes my.class.js so fast?
Properties of Javascript function objects
I need some help here to undestand how this works (or does not, for that matter).
In a web page, I create a click event listener for a node.
Within the listener, I create an instance of some random class, which sets the node as property within itself. So, if var classInstance is the instance, I can access the node as something like classInstance.rootNode.
When the listener fires, I setup an ajax request, keep classInstance in closure and pass along the ajax response to classInstance and use it to perhaps modify the rootNode's style or content or whatever.
My question is, once I'm done with classInstance, assuming nothing else references it and by itself, it holds nothing else in its own closure, will the garbage collector dispose of it? If not, how do I mark it for disposal?
In response to #Beetroot-Beetroot's doubts (which, admittedly, I have, too), I did some more digging. I set up this fiddle, and used the chrome dev-tools' timeline and this article as a guideline. In the fiddle, two almost identical handlers create a closure with 2 date objects. The first only references a, the second references both a and b. Though in both cases only a can ever really be exposed (hard-coded values), the first closure uses significantly less memory. Whether or not this is down to JIC (just in time compilation) or V8's JS optimization wizardry, I can't say for sure. But from what I've read, I'd say it's V8's GC that deallocates b when the tst function returns, which it can't in the second case (bar references b when tst2 returns). I get the feeling that this isn't that outlandish, and I wouldn't at all be surprised to find out that FF and even IE would work similarly. Just added this, perhaps irrelevant, update for completeness' sake and because I feel as though a link to google's documentation of the dev-tools is an added value of sorts.
It sort of depends, as a simple rule of thumb: as long as you can't reference the classInstance variable anymore, it should be GC'ed, regardless of its own circular references. I've tested quite a lot of constructions, similar to the one you describe here. Perhaps it's worth a lookI've found that closures and mem-leaks aren't that common or easy to get by (at least, not anymore).
But as the accepted answer says: it's nigh impossible to know when what code will leak. Reading over your question again, I'd say: no, you're not going to leak memory: the classInstance variable wasn't created in the global scope, but it's being passed to various functions (and therefore various scopes). These scopes disintegrate each time the function returns. classInstance won't be GC'ed if it's been passed to another function/scope. But as soon as the last function that references classInstance returns, the object is marked for GC. Sure it might be a circular reference, but it's a reference that cannot be accessed from anywhere but its own scope. You can't really call that a closure, either: closures happen when there is some form of exposure to the outer scope, which is not happening in your example.
I'm rubbish at explaining stuff like this, but just to recap:
var foo = (function()
{
var a, b, c, d;
return function()
{
return a;
}
})();
The GC will deallocate the mem b,c and d reference: they've gone out of scope, there's no way to access them...
var foo = (function()
{
var a, b, c, d;
return function()
{
a.getB = function()
{
return b;
}
a.getSelf = function()
{
return a;//or return this;
}
return a;
}
})();
//some code
foo = new Date();//
In this case, b won't get GC'ed either, for obvious reasons. foo exposes a and b, where a is an object that contains a circular reference. Though as soon as foo = new Date(), foo loses any reference to a. Sure, a still references itself, but a is no longer exposed: it can reference whatever it bloody well likes. Most browsers won't care and will GC a and b. In fact, I've checked and Chrome, FF, and IE8 all GC the code above perfectly... no worries, then.
I'm not an expert on this issue, but I'm pretty sure the GC will not dispose of it. In fact, it probably never will, because you've created a circular reference between the event listener and the DOM node. To allow it to be garbage-collected, you should set one or both of those references (the event listener and/or rootNode) to undefined or null.
Still, I'd only worry about this if you're creating many of these classInstances or if it can be created several times over the page's lifetime. Otherwise it's an unnecessary optimization.
Coming from C++ it is hard grained into my mind that everytime I call new I call delete. In JavaScript I find myself calling new occasionally in my code but (hoping) the garbage collection functionality in the browser will take care of the mess for me.
I don't like this - is there a delete method in JavaScript and is how I use it different from in C++?
Thanks.
var component = new Component();
component = null; // delete this at next garbage collection
Incidentally, the "new" keyword isn't really necessary in javascript, and has nothing (directly) to do with allocating memory. All "new" does is pass a new, empty object called "this" (this = {}) as a hidden argument to the function.
var MyClass = function(){
// fresh empty object "this" gets passed to function
// when you use the "new" keyword
this.method = function(){}
}
var myInstance = new MyClass();
Javascript can get kind of hairy with nested closures and multiple "this" variables floating around in different scopes. I prefer to do it this way:
var MyNoNewClass = function(){
// I find this more explicit and less confusing
var self = {}
self.method = function(){}
return self;
}
var myNoNewInstance = MyNoNewClass()
All JavaScript memory is referenced, but not in the traditional sense. Memory is referenced not by memory address but by a string. In this code:
var x = new someObj();
That object is referenced by the string "x" from that point forward. x is not a pointer to some memory on the heap at that point. If you assigned x a property then:
x.someProp = 42;
Then someProp is a string in memory referencing the value 42. Consequently that lets you use array notation to access it by it's string representation:
x["someProp"]++;
It's also why variables can hold any value as they don't have need of size.
Memory is collected in JavaScript, effectively, when no more strings (aka variables or property names) are referencing it. That object will be collected when x is assigned any other value. You could set it to null, undefined, or anything else and that memory will be collected.
That is, it will be collected when the browser or whatever JavaScript engine gets around to it.
Delete only removes properties from objects. From then on attempting to access that property will return undefined. For the most part, the following 2 lines of code are equivalent:
x["someProp"] = undefined;
delete x.someProp;
Edit: Ok, internally the two lines aren't the same. The delete operator will remove the "someProp" reference from memory, while setting it to undefined won't. I think. I can't find anything in the specs about setting a variable or property to undefined, but I don't think doing so does anything special.
The important thing to note is that you won't be able to delete properties that have a certain flag set, but you can set them to null or undefined (if they're not wrapped by a setter and even allow that to happen).
Taken outside of the context (the browser) the javascript is fully capable of reclaiming the memory through garbage collection. Going back to reality garbage collection in combination with DOM model can cause memory leaks.
Here is one article http://www.ibm.com/developerworks/web/library/wa-memleak/ you can find more details about it
To avoid memory leaks
Ensure you remove all event handlers, so if you add like a mouse down event handler ensure you remove it when you finish
if you add elements to the DOM, remove them when done
if you have an object that points to another object, remove the reference when the object is done with.
when you are finish with any object set it to null.
deletes just gonna remove a property from an object.
There is a delete. However, an actual need for it will be rare. It's not like C++ delete, though.
delete in JavaScript will remove a property from an object. Subsequent accesses of that property will return undefined. I assume it will be able to free any associated memory on subsequent garbage collects.
Don't use delete in JavaScript unless you are removing event handlers. Even then, we only do this because there is a memory leak associated with this practice in older versions of IE. Douglas Crockford explains this pretty well. In his case, he doesn't even use delete. He simply sets the values in question to null.
From the MDC:
The delete operator deletes a property of an object, or an element at a specified index in an array.
The delete operator in my opinion is only useful when you want to remove a property from an object. But since there might be other references to the property that it were referencing, it wont be really GCed. If you want something to be GCed, you need to remove all pointers pointing at it and also free the closures containing references to it (more info on the topic).
new creates objects from a constructor. delete removes properties from an object. These are two very different things.
You don't have to delete objects you created. The GC takes care of this.
delete o.fu is different from o.fu = undefined. Try this:
var o = {};
alert(o.hasOwnProperty('fu')); // -> false
o.fu = undefined;
alert(o.hasOwnProperty('fu')); // -> true
delete o.fu;
alert(o.hasOwnProperty('fu')); // -> false
There is a delete in Javascript, but trust me: it's way different than delete in something like C++. I recommend you don't even think about using it until you're more comfortable with Javascript.
Garbage collection works, though it doesn't defeat the problem of memory leaks.
The "new" keyword has nothing to do with memory. It's purpose is only to setup the prototype chain.
// C++
Foo* foo = new Foo(); // allocate and construct
// JS "sugar" using the new keyword
var foo = new Foo(); // allocate and construct
assert(foo instanceof Foo);
// JS constructing objects without "new"
var foo = Object.create(Foo.prototype); // allocate with prototype
Foo.call(foo); // construct
assert(foo instanceof Foo);
// construct Foo with missing prototype
var foo = {}; // allocate without prototype
Foo.call(foo); // construct without prototype
assert(!(foo instanceof Foo));
// so the corollary operations in JS are
foo = {};
foo = null;
// where-as this is an error (or most certainly not what you want)
delete foo;
// and this is how delete is used
foo = {bar: 42};
assert(foo.bar === 42);
delete foo.bar;
assert(foo.bar === undefined);
// but by deleting a property, you remove the reference to the object
foo = {bar: {baz: 31}};
delete foo.bar; // remove only reference to "bar" object
// JS GC will now take over
So no, you can't delete objects. But you can delete references to objects, which may trigger object deletion by the GC. But of course, local variables (and global) can't be deleted. They simply go out of scope, de-referencing any associated objects, and potentially freeing memory, but only if the object wasn't returned or is still referenced elsewhere.
It's important to realize that because JS doesn't support pointers, GC can be perfect. At any point, the GC can simply walk the entire set of objects "seen" from any in-scope function and guarantee it doesn't miss anything like cycles, etc.
As long as you use JS in a functional style and don't try to build global god objects which tie everything together, memory management should be a non-issue.