Javascript: What happens to objects that don't have a name? - javascript

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

Related

Why does an object created and returned by a function continue to exist after the function execution ends?

I read that every function has its own stack, which means that when the function ends its variables are no longer kept into the memory. I read also that objects are returned by reference.
Consider this example:
function getObject() {
var obj = {name: "someName"};
return obj;
} //At the end the locals should disappear
var newObj = getObject();// Get reference to something that is no longer kept in the stack,
console.log(newObj);//
So if the returned value by the function is a reference to an object that no longer exists (in the stack), how are we still getting the right value? In C (language) to return a pointer to a local variable is insane.
First, a quick disclaimer: There's a difference here between the theory and the optimized process that modern JavaScript engines actually perform.
Let's start with the theory:
The object isn't on the stack, just the variable that contains the reference to the object. The object exists separately, and is created in the heap. So in your example, just before the function returns, we have this in memory:
+−−−−−−−−−−−−−−−−−−+
| (object) |
+−−−−−−−−−−−−−−−−−−+
[obj:Ref11254]−−−−−>| name: "someName" |
+−−−−−−−−−−−−−−−−−−+
obj, the variable, contains a reference to the object (Ref11254, though of course that's just a conceptual number, we never actually see these). When your function returns, the content of obj (Ref11254) is returned, and obj (the variable) disappears along with the rest of the stack. But the object, which exists separately, continues to exist as long as something has a reference to it — in your case, the newObj variable.
In practice:
As an optimization, modern JavaScript engines frequently allocate objects on the stack (subject to engine-specific size constraints). Then, if the object is going to continue to live after the function terminates and the stack is cleaned up, they copy it into the heap. But if the object isn't going to survive (that is, no reference to it has been kept or is being returned), they can let it get cleaned up along with the stack. (Why? Because stack allocations and cleanup are really fast, and a lot of objects are only used locally in functions.)
It's worth noting that the same question arises for variables if the function creates a function:
function getFunction() {
var x = 0;
return function() {
return x++;
};
}
var f = getFunction();
console.log(f()); // 0
console.log(f()); // 1
console.log(f()); // 2
Now it's not just that the function getFunction returns (which is an object) survives, but so does x! Even though variables are "on the stack," and the stack gets reclaimed when getFunction returns. How is that possible?!
The answer is that conceptually, local variables aren't on the stack. Putting them on the stack is an optimization (a common one). Conceptually, local variables (along with a few other things) are stored in an object called a LexicalEnvironment object which is created for the call to getFunction. And conceptually, the function getFunction returns has a reference to that LexicalEnvironment object, and so it (and the variables it contains) continues to live on even after getFunction returns. (The function getFunction returns is called a closure because it closes over the environment where it was created.)
And sure enough, in practice modern JavaScript engines don't really do that. They create variables on the stack where it's quick and easy to clean them up. But then if a variable is going to need to live on (like x needs to in our example above), the engine puts it (and any others that it needs to keep around) into a container in the heap and has the closure refer to that container.
More about closures in this question's answers and on my anemic little blog (using slightly outdated terminology).
Because the garbage collector is clever than that! Simply put, if the object has active references then it isn't removed. Variables created within the function and not returned are lost when the function ends (unless you've created async calls which use them) but because they then don't have any active references.
See, for example, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

Why is chrome forgetting about variable references? [duplicate]

as ECMAScriptv5, each time when control enters a code, the enginge creates a LexicalEnvironment(LE) and a VariableEnvironment(VE), for function code, these 2 objects are exactly the same reference which is the result of calling NewDeclarativeEnvironment(ECMAScript v5 10.4.3), and all variables declared in function code are stored in the environment record componentof VariableEnvironment(ECMAScript v5 10.5), and this is the basic concept for closure.
What confused me is how Garbage Collect works with this closure approach, suppose I have code like:
function f1() {
var o = LargeObject.fromSize('10MB');
return function() {
// here never uses o
return 'Hello world';
}
}
var f2 = f1();
after the line var f2 = f1(), our object graph would be:
global -> f2 -> f2's VariableEnvironment -> f1's VariableEnvironment -> o
so as from my little knowledge, if the javascript engine uses a reference counting method for garbage collection, the object o has at lease 1 refenrence and would never be GCed. Appearently this would result a waste of memory since o would never be used but is always stored in memory.
Someone may said the engine knows that f2's VariableEnvironment doesn't use f1's VariableEnvironment, so the entire f1's VariableEnvironment would be GCed, so there is another code snippet which may lead to more complex situation:
function f1() {
var o1 = LargeObject.fromSize('10MB');
var o2 = LargeObject.fromSize('10MB');
return function() {
alert(o1);
}
}
var f2 = f1();
in this case, f2 uses the o1 object which stores in f1's VariableEnvironment, so f2's VariableEnvironment must keep a reference to f1's VariableEnvironment, which result that o2 cannot be GCed as well, which further result in a waste of memory.
so I would ask, how modern javascript engine (JScript.dll / V8 / SpiderMonkey ...) handles such situation, is there a standard specified rule or is it implementation based, and what is the exact step javascript engine handles such object graph when executing Garbage Collection.
Thanks.
tl;dr answer: "Only variables referenced from inner fns are heap allocated in V8. If you use eval then all vars assumed referenced.". In your second example, o2 can be allocated on the stack and is thrown away after f1 exits.
I don't think they can handle it. At least we know that some engines cannot, as this is known to be the cause of many memory leaks, as for example:
function outer(node) {
node.onclick = function inner() {
// some code not referencing "node"
};
}
where inner closes over node, forming a circular reference inner -> outer's VariableContext -> node -> inner, which will never be freed in for instance IE6, even if the DOM node is removed from the document. Some browsers handle this just fine though: circular references themselves are not a problem, it's the GC implementation in IE6 that is the problem. But now I digress from the subject.
A common way to break the circular reference is to null out all unnecessary variables at the end of outer. I.e., set node = null. The question is then whether modern javascript engines can do this for you, can they somehow infer that a variable is not used within inner?
I think the answer is no, but I can be proven wrong. The reason is that the following code executes just fine:
function get_inner_function() {
var x = "very big object";
var y = "another big object";
return function inner(varName) {
alert(eval(varName));
};
}
func = get_inner_function();
func("x");
func("y");
See for yourself using this jsfiddle example. There are no references to either x or y inside inner, but they are still accessible using eval. (Amazingly, if you alias eval to something else, say myeval, and call myeval, you DO NOT get a new execution context - this is even in the specification, see sections 10.4.2 and 15.1.2.1.1 in ECMA-262.)
Edit: As per your comment, it appears that some modern engines actually do some smart tricks, so I tried to dig a little more. I came across this forum thread discussing the issue, and in particular, a link to a tweet about how variables are allocated in V8. It also specifically touches on the eval problem. It seems that it has to parse the code in all inner functions. and see what variables are referenced, or if eval is used, and then determine whether each variable should be allocated on the heap or on the stack. Pretty neat. Here is another blog that contains a lot of details on the ECMAScript implementation.
This has the implication that even if an inner function never "escapes" the call, it can still force variables to be allocated on the heap. E.g.:
function init(node) {
var someLargeVariable = "...";
function drawSomeWidget(x, y) {
library.draw(x, y, someLargeVariable);
}
drawSomeWidget(1, 1);
drawSomeWidget(101, 1);
return function () {
alert("hi!");
};
}
Now, as init has finished its call, someLargeVariable is no longer referenced and should be eligible for deletion, but I suspect that it is not, unless the inner function drawSomeWidget has been optimized away (inlined?). If so, this could probably occur pretty frequently when using self-executing functions to mimick classes with private / public methods.
Answer to Raynos comment below. I tried the above scenario (slightly modified) in the debugger, and the results are as I predict, at least in Chrome:
When the inner function is being executed, someLargeVariable is still in scope.
If I comment out the reference to someLargeVariable in the inner drawSomeWidget method, then you get a different result:
Now someLargeVariable is not in scope, because it could be allocated on the stack.
There is no standard specifications of implementation for GC, every engine have their own implementation. I know a little concept of v8, it has a very impressive garbage collector (stop-the-world, generational, accurate). As above example 2, the v8 engine has following step:
create f1's VariableEnvironment object called f1.
after created that object the V8 creates an initial hidden class of f1 called H1.
indicate the point of f1 is to f2 in root level.
create another hidden class H2, based on H1, then add information to H2 that describes the object as having one property, o1, store it at offset 0 in the f1 object.
updates f1 point to H2 indicated f1 should used H2 instead of H1.
creates another hidden class H3, based on H2, and add property, o2, store it at offset 1 in the f1 object.
updates f1 point to H3.
create anonymous VariableEnvironment object called a1.
create an initial hidden class of a1 called A1.
indicate a1 parent is f1.
On parse function literal, it create FunctionBody. Only parse FunctionBody when function was called.The following code indicate it not throw error while parser time
function p(){
return function(){alert(a)}
}
p();
So at GC time H1, H2 will be swept, because no reference point that.In my mind if the code is lazily compiled, no way to indicate o1 variable declared in a1 is a reference to f1, It use JIT.
if the javascript engine uses a reference counting method
Most javascript engine's use some variant of a compacting mark and sweep garbage collector, not a simple reference counting GC, so reference cycles do not cause problems.
They also tend to do some tricks so that cycles that involve DOM nodes (which are reference counted by the browser outside the JavaScript heap) don't introduce uncollectible cycles. The XPCOM cycle collector does this for Firefox.
The cycle collector spends most of its time accumulating (and forgetting about) pointers to XPCOM objects that might be involved in garbage cycles. This is the idle stage of the collector's operation, in which special variants of nsAutoRefCnt register and unregister themselves very rapidly with the collector, as they pass through a "suspicious" refcount event (from N+1 to N, for nonzero N).
Periodically the collector wakes up and examines any suspicious pointers that have been sitting in its buffer for a while. This is the scanning stage of the collector's operation. In this stage the collector repeatedly asks each candidate for a singleton cycle-collection helper class, and if that helper exists, the collector asks the helper to describe the candidate's (owned) children. This way the collector builds a picture of the ownership subgraph reachable from suspicious objects.
If the collector finds a group of objects that all refer back to one another, and establishes that the objects' reference counts are all accounted for by internal pointers within the group, it considers that group cyclical garbage, which it then attempts to free. This is the unlinking stage of the collectors operation. In this stage the collector walks through the garbage objects it has found, again consulting with their helper objects, asking the helper objects to "unlink" each object from its immediate children.
Note that the collector also knows how to walk through the JS heap, and can locate ownership cycles that pass in and out of it.
EcmaScript harmony is likely to include ephemerons as well to provide weakly held references.
You might find "The future of XPCOM memory management" interesting.

Does this javascript pattern encourage memory leaks?

I am finding myself rather confused regarding javascript garbage collection and how to best encourage it.
What I would like to know is related to a particular pattern. I am not interested in whether the pattern itself is considered a good or bad idea, I am simply interested in how a browsers garbage collector would respond, i.e would the references be freed and collected or would it cause leaks.
Imagine this pattern:
TEST = {
init : function(){
this.cache = {
element : $('#element')
};
},
func1 : function(){
this.cache.element.show();
},
func2 : function(){
TEST.cache.element.show();
},
func3 : function(){
var self = this;
self.cache.element.show();
},
func4 : function(){
var element = this.cache.element;
element.show();
}
func5 : function(){
this.auxfunc(this.cache.element);
}
auxfunc1 : function(el){
el.show();
}
func6 : function(){
var el = getElement();
el.show();
}
getElement : function(){
return this.cache.element;
}
}
Now imagine that on page load TEST.init() is called;
Then later at various times the various functions are called.
What I would like to know is if caching elements or objects or anything else upon initialization and referring to them throughout the lifetime of an application, in the manner shown above, effects a browsers garbage collector positively or negatively.
Is there any difference? Which method best encourages garbage collection? Do they cause leaks? Are there any circular references? if so where?
This code, in itself, shouldn't cause any memory leaks. Especially not in modern browsers. It's just an object, like you have tons of others in any script. It all depends on where, how, and how long you reference it.
The basic rule is that, whenever an object is no longer referenced anywhere in the code (directly/by variable or indirectly/ through closure accessing a scope), the GC will flag and swipe.
If you use the above code, and then assign something else to TEST the object literal it referenced could be GC'ed, if no other variable references the original object.
Of course, predicting memory leaks in JS is an inexact science. In my experience, they're not nearly as common as some would have you believe. Firebug, Chrome's console (profiler) and IE debugger get you along a long way.
Some time ago I did some more digging into this matter resulting in this question. Perhaps some links, and findings are helpful to you...
If not here's a couple of tips to avoid the obvious leaks:
Don't use global variables (they don't actually leak memory permanently, but do so, for as long as your script runs).
Don't attach event handlers to the global object (window.onload ==> leaks mem in IE <9 because the global object is never fully unloaded, hence the event handler isn't GC'ed)
Just wrap your script in a huge IIFE, and use strict mode whenever possible. That way, you create a scope that can be GC'ed in its entirety on unload.
Test, test and test again. Don't believe every blogpost you read on the subject! If something was an issue last year, that needn't be the case today. This answer might not be 100% accurate anymore by the time you read this, or because just this morning some miracle-patch for JS GC'ing was written by erm... Paris Hilton or some other alien life-form.
Oh, and to answer your in-comment question: "But what concerns me is if each time i call this.cache.element, is it creating a new reference within that functions scope ON TOP of the original cache reference which will not be garbage collected?"
The answer is no. Because this will reference the TEST object, and the init function assigns the object a property cahche, that in itself is another object literal with 1 property referencing a jQ object. That property (cache) and all that is accessible through it will sit in memory right until you either delete TEST.cache or delete TEST. if you were to create var cahce = {...}; that object would be GC'ed when the ini function returns, because a variable cannot outlive its scope, except for when you're using closures and exposing certain variables indirectly.

Garbage collection in JavaScript closures

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.

JavaScript new keyword and memory management

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.

Categories