Javascript "saves" function data in memory? - javascript

Example :
var myFunctArray=new Array();
for(var i=0; i<10; i++) {
addValues(i);
}
function addValues(myPoint)
{
myFunct=function () {
var myVar="Line " + myPoint;
console.log(myVar);
}
myFunctArray.push(myFunct);
}
myFunctArray[3]();
when I call the 4° function, how can it remembers the value of myPoint? In fact it is Line 3 the output, so myPoint value must be "stored" somewhere, for each function.
So, it stores 10 "definitions" of myFunct in the stack memory?
Hope it is clear what I mean.

It's called a closure. Any variables that are currently in scope when you create a new function are associated with that closure.

So, it stores 10 "definitions" of myFunct in the stack memory?
Yes, it does.
Your array contains ten closures, each of which has captured its own version of myPoint.

Thiefmaster answered your question pretty much. Yes, this code will use more and more memory, depending on how many closures your array contains. It has to be said that most modern engines will assign a reference to the function assigned to the MyFunct variable and a specific "call object" that contains the closure vars. In other words, your array will look something along the lines of:
myFuncArray[0] = {call:
{myPoint:'Whatever value was passed to the addValues function the first time'},
valueOf: myFunct};
//the actual value is a reference to myFunct
//JS provides an implicit link to the call property, which is bound to this particular reference
myFuncArray[1] = {call:
{myPoint:'The value passed to addValues the second time'},
valueOf: myFunct};
You don't have access to the object as such, but this is just the way to think of how JS will keep things organized in memory.
Slightly off topic, but you're creating an implied global with your MyFunct variable:
function addValues(myPoint)
{
var anotherClosureVar = 'This will be accessible, too: it\'s part of the closure';
var myFunct = function()
{//use var to declare in addValues scope, instead of using an implied global
var myVar="Line " + myPoint;
console.log(myVar);
console.log(anotherClosureVar);//will work, too
};
myFunctArray.push(myFunct);
}
All in all, if this is your code, memory shouldn't be that big of an issue. Even if this code were to run on an old JScript engine, it'll take some time before you've used up a meaningful amount of memory. Still, it's a good habit to think about stuff like this, and I do hope I made sense here, I'm not a native speaker, which makes explaining the more abstract aspects of JS somewhat tricky

Related

Javascript function stored in array vs in a variable

In this example why does pushing the function reference onto the array not change the scope execution context of this whereas assigning the function reference to a new variable does change the scope execution context of this?
(function() {
function Car(year) {
this.year = year;
}
Car.prototype = {
logYear: function() {
console.log(this.year);
}
};
var ford = new Car('Ford', 1999);
ford.logYear();
var cbs = [];
cbs.push(ford.logYear);
for(var x = 0; x < cbs.length; x++) {
cbs[x](); // -> 1999 #1
var callback = cbs[x];
callback(); // -> undefined #2
}
})()
Is this because the reference to the function in the array points to the original function on the ford object where this is still defined as the instance (#1) and the variable assignment changes the this to point to the wrapping IIFE block (#2)?
Is this a good pattern if I need to collect of bunch of methods like this from various objects and call them somewhere else?
How does this referential calling relate to examples like console.error.bind(console)?
Thanks!
-- Update
Thanks to #Satyajeet for the nice explanation and clarification.
Typos & copying errors aside the reason I was asking this question in the first place is that I suspected what Satyajeet confirmed but an application I am working on does not reflect this behavior (or so I thought).
It turns out that in the application I am performing a similar process to the above code where I call cbs.push(ford.logYear);, adding multiple methods from different objects to an array.
At a point in the app I call all these methods and expect them to behave in the same way as when they are called in the execution context scope of the original object... and they do, because the values the methods interact with are not attached to this, they are captured in closures.
See example plunker here
-- Update 2
Fixed usage of execution context and scope to be accurate for each part of the question/answer.
Ignoring your late night copy paste mistake, and redefining your Car function to
function Car(name, year) {
this.name = name;
this.year = year
}
#1 indeed more of a question about how Array works rather then about the context and scope(*#2)
You are calling a function inside an array, So in javascript each element of an array is a property of that Array Object. for example
var a = [];
a.push('Some value'); // a.0 is a property
but you just can not call a.0 because in javascript properties that begin with a digit cannot be referenced with dot notation, and must be accessed using bracket notation
So when you are calling cbx[0]() it is essentially same as cbx.0().
And here comes the role of Scope and Execution context in javascript. There are already many good articles and answers about Scope and Context in javascript. Just like this, So i think its not worth to explain all that here.
But fundamentally this is not defined till the execution of function(this depends on Execution context rather then scope).
So your #1 will print undefined because cbs[0]() is equivalent to cbs.0(), And this(Execution context) is set to Array itself, which is [function]. (You only have a function inside it).
And your #2 will also print undefined because Execution context is global(window object in case of browser) there.
Answer to your 3rd question is, You need to Explicitly hard bind Execution context to your function.
cbs.push(ford.logYear.bind(ford));
And your 4th question is i think just an another use case of ES5's bind method, Nothing special. It is normally used because browser implementations requires that execution context(this) of console.error must be set to window.console.

Definition of 'closures'

Let me ask one question. It's about closures in JavaScript, but not about how they work.
David Flanagan in his "JavaScript The Definitive Guide 6th Edition" wrote:
...Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them....
Is this correct? Can I call every function (function object + it's scope) a "closure"?
And stacks' tag "closures" says:
A closure is a first-class function that refers to (closes over) variables from the scope in which it was defined. If the closure still exists after its defining scope ends, the variables it closes over will continue to exist as well.
In JavaScript every function refers to variables from the scope in which it was defined. So, It's still valid.
The question is: why do so many developers think otherwise? Is there something wrong with this theory? Can't it be used as general definition?
Technically, all functions are closures. But if the function doesn't reference any free variables, the environment of the closure is empty. The distinction between function and closure is only interesting if there are closed variables that need to be saved along with the function code. So it's common to refer to functions that don't access any free variables as functions, and those that do as closures, so that you know about this distinction.
It's a tricky term to pin down. A function that's simply declared is just a function. What makes a closure is calling the function. By calling a function, space is allocated for the parameters passed and for local variables declared.
If a function simply returns some value, and that value is just something simple (like, nothing at all, or just a number or a string), then the closure goes away and there's really nothing interesting about it. However, if some references to parameters or local variables (which, mostly, are the same) "escape" the function, then the closure — that space allocated for local variables, along with the chain of parent spaces — sticks around.
Here's a way that some references could "escape" from a function:
function escape(x, y) {
return {
x: x,
y: y,
sum: function() { return x + y; }
};
}
var foo = escape(10, 20);
alert(foo.sum()); // 30
That object returned from the function and saved in "foo" will maintain references to those two parameters. Here's a more interesting example:
function counter(start, increment) {
var current = start;
return function() {
var returnValue = current;
current += increment;
return returnValue;
};
}
var evenNumbers = counter(0, 2);
alert(evenNumbers()); // 0
alert(evenNumbers()); // 2
alert(evenNumbers()); // 4
In that one, the returned value is itself a function. That function involves code that makes reference to the parameter "increment" and a local variable, "current".
I would take some issue with conflating the concept of a closure and the concept of functions being first-class objects. Those two things really are separate, though they're synergistic.
As a caveat, I'm not a formalist by basic personality and I'm really awful with terminology so this should probably be showered with downvotes.
I would try to answer your question knowing you were asked about what closures are during the interview (read it from the comments above).
First, I think you should be more specific with "think otherwise". How exactly?
Probably we can say something about this noop function's closure:
function() {}
But it seems it has no sense since there are no variables would bound on it's scope.
I think even this example is also not very good to consider:
function closureDemo() {
var localVar = true;
}
closureDemo();
Since its variable would be freed as there is no possibility to access it after this function call, so there is no difference between JavaScript and let's say C language.
Once again, since you said you have asked about what closures are on the interview, I suppose it would be much better to show the example where you can access some local variables via an external function you get after closureDemo() call, first. Like
function closureDemo() {
var localVar = true;
window.externalFunc = function() {
localVar = !localVar; // this local variable is still alive
console.log(localVar); // despite function has been already run,
// that is it was closed over the scope
}
}
closureDemo();
externalFunc();
externalFunc();
Then to comment about other cases and then derive the most common definition as it more likely to get the interviewer to agree with you rather than to quote Flanagan and instantly try to find the page where you've read it as a better proof of your statement or something.
Probably your interviewer just thought you don't actually know about what closures are and just read the definition from the book. Anyhow I wish you good luck next time.
The definition is correct.
The closure keeps the scope where it was born
Consider this simple code:
getLabelPrinter = function( label) {
var labelPrinter = function( value) {
document.write(label+": "+value);
}
return labelPrinter; // this returns a function
}
priceLabelPrinter = getLabelPrinter('The price is');
quantityLabelPrinter = getLabelPrinter('The quantity is');
priceLabelPrinter(100);
quantityLabelPrinter(200);
//output:
//The price is: 100 The quantity is: 200
https://jsfiddle.net/twqgeyuq/

Can you get the property name through which a function was called?

I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.
A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.
(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)
My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.
Here's an example of what I want to do:
var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };
callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).
I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)
Can this be done?
Short answer:
No, you cannot get "the property name" used to call your function.
There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
arguments.callee is deprecated and should not be used.
There exists no solution that does not use arguments or closure.
Long answer:
As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".
The reason is because it is not simple.
Before we go ahead, let us clarify something. Activation Objects are not objects at all.
The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain.
In a browser the global scope is (often) the window object, but all other scopes are not objects.
There may be an object that you use to call a function, and when you call a function you must be in some scope.
With few exceptions, scopes are not objects, and objects are not scopes.
Then, there are many names.
When you call a function, you need to reference it, such as through an object property. This reference may have a name.
Scope chain has declarations, which always have a name.
A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.
Not only are they different names, they are not (always) the "the property name" you are seeking.
var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)
So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable.
They are all References (8.7). And reference does have a name (so to speak).
The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined.
For example a common closure technique:
(function(i){ /* what is my name? */ })(i)
Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way.
Which keeps the JavaScript engine sane. Consider this example:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.
If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them?
Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.
This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated.
The "property name" of a function is even more ill defined than the caller, almost unrealistic.
At least caller is always an execution context (not necessary a function).
So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.
there is no reflection, but you can use function behavior to make adding your own fairly painless, and without resorting to try/catch, arguments.callee, Function.caller, or other strongly frowned-upon behavior, just wasteful looping:
// returning a function from inside a function always creates a new, unique function we can self-identify later:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//the one ugly about this is the extra "()" at the end:
var obj1 = {'callName2':callName(), 'callName3':callName() };
var obj2 = {'callName4':callName(), 'callName5':callName() };
//test out the tattle-tale function:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
if you REALLY want to make it look like an assignment and avoid the execution parens each time in the object literal, you can do this hacky routine to create an invoking alias:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//make an alias to execute a function each time it's used :
Object.defineProperty(window, 'callNamer', {get: function(){ return callName() }});
//use the alias to assign a tattle-tale function (look ma, no parens!):
var obj1 = {'callName2': callNamer, 'callName3': callNamer };
var obj2 = {'callName4': callNamer, 'callName5': callNamer };
//try it out:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
all that aside, you can probably accomplish what you need to do without all the looping required by this approach.
Advantages:
works on globals or object properties
requires no repetitive key/name passing
uses no proprietary or deprecated features
does not use arguments or closure
surrounding code executes faster (optimized) than
a try/catch version
is not confused by repeated uses
can handle new and deleted (renamed) properties
Caveats:
doesn't work on private vars, which have no property name
partially loops owner object each access
slower computation than a memorized property or code-time repetition
won't survive call/bind/apply
wont survive a setTimeout without bind() or a wrapper function
cannot easily be cloned
honestly, i think all the ways of accomplishing this task are "less than ideal", to be polite, and i would recommend you just bite the coding bullet and pass extra key names, or automate that by using a method to add properties to a blank object instead of coding it all in an object literal.
Yes.
Sort Of.
It depends on the browser. (Chrome=OK, Firefox=Nope)
You can use a factory to create the function, and a call stack parsing hack that will probably get me arrested.
This solution works in my version of Chrome on Windows 7, but the approach could be adapted to other browsers (if they support stack and show the property name in the call stack like Chrome does). I would not recommend doing this in production code as it is a pretty brittle hack; instead improve the architecture of your program so that you do not need to rely on knowing the name of the calling property. You didn't post details about your problem domain so this is just a fun little thought experiment; to wit:
JSFiddle demo: http://jsfiddle.net/tv9m36fr/
Runnable snippet: (scroll down and click Run code snippet)
function getCallerName(ex) {
// parse the call stack to find name of caller; assumes called from object property
// todo: replace with regex (left as exercise for the reader)
// this works in chrome on win7. other browsers may format differently(?) but not tested.
// easy enough to extend this concept to be browser-specific if rules are known.
// this is only for educational purposes; I would not do this in production code.
var stack = ex.stack.toString();
var idx = stack.indexOf('\n');
var lines = ex.stack.substring(idx + 1);
var objectSentinel = 'Object.';
idx = lines.indexOf(objectSentinel);
var line = lines.substring(idx + objectSentinel.length);
idx = line.indexOf(' ');
var callerName = line.substring(0, idx);
return callerName;
}
var Factory = {
getFunction: function () {
return function () {
var callName = "";
try {
throw up; // you don't *have* to throw to get stack trace, but it's more fun!
} catch (ex) {
callName = getCallerName(ex);
}
alert(callName);
};
}
}
var obj1 = {
'callName2': Factory.getFunction(),
'callName3': Factory.getFunction()
};
var obj2 = {
'callName4': Factory.getFunction(),
'callName5': Factory.getFunction()
};
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'

deeper understanding of closure in Javascript

I was reading the comments on an answer and saw this comment:
[the closure] doesn't persist the state of foo so much as creates a special scope containing (1) the returned function and (2) all the external variables referenced at the time of the return. This special scope is called a closure.
OK, so far so good. Now here is the interesting part that I didn't know about:
Case in point... if you had another var defined in foo that was not referenced in the return function, it would not exist in the closure scope.
I guess that makes sense, but what implications does this have other than memory use / perfomance?
Question -- If all variables in scope were included in the closure, what would that allow me to do that I cannot do with the current model?
I think you're taking that comment too literally. The comment is just saying that you can't access it outside the function scope (it's not publicly accessible), not that its not available at all within the function. The returned function will have access to all of the outer functions scope no matter what. You just can't access that scope outside the outer function if the inner function doesn't provide a way of accessing it.
For instance, this expression evaluates to 4:
function testClosure(){
var x = 2;
return function(y){
alert(eval(y));
}
}
var closure = testClosure();
closure("x+2"); //4
http://jsfiddle.net/dmRcH/
So x is available despite not being directly referenced
Further research
It appears that chrome and firefox at least do attempt to optimize this in the sense that if you're not providing ANY way to reference the x variable, it doesn't show up as being available in the debugger. Running this with a breakpoint inside a closure shows x as unavailable on Chrome 26 and Firefox 18.
http://jsfiddle.net/FgekX/1/
But thats just a memory management detail, not a relevant property of the language. If there is any possible way that you could reference the variable, it is passed, and my suspicion is that other browsers may not optimize this in the same way. Its always better to code to the spec than to an implementation. In this case though the rule really is: "if there's any possible way for you to access it, it will be available". And also, don't use eval because it really will keep your code from optimizing anything.
if you had another var defined in foo that was not referenced in the return function, it would not exist in the closure scope.
This is not entirely accurate; the variable is part of the closure scope, even though it may not be directly referenced inside the function itself (by looking at the function code). The difference is how the engines optimize unused variables.
For instance, unused variables in the closure scope are known to cause memory leaks (on certain engines) when you're working with DOM elements. Take this classical example for instance:
function addHandler() {
var el = document.getElementById('el');
el.onclick = function() {
this.style.backgroundColor = 'red';
}
}
Source
In above code, memory is leaked (in both IE and Mozilla at least) because el is part of the closure scope for the click handler function, even though it's not referenced; this causes a cyclic reference which can't be removed because their garbage collection is based on reference counting.
Chrome, on the other hand, uses a different garbage collector:
In V8, the object heap is segmented into two parts: new space where objects are created, and old space to which objects surviving a garbage collection cycle are promoted. If an object is moved in a garbage collection cycle, V8 updates all pointers to the object.
This is also referred to as a generational or ephemeral garbage collector. Albeit more complicated, this type of garbage collector can more accurately establish whether a variable is used or not.
JavaScript has no inherent sense of privacy so we use function scope (closure) to simulate this functionality.
The SO answer you reference is an example of the Module pattern which Addy Osmani does a great job explaining the importance of in Learning JavaScript Design Patterns:
The Module pattern encapsulates "privacy", state and organization
using closures. It provides a way of wrapping a mix of public and
private methods and variables, protecting pieces from leaking into the
global scope and accidentally colliding with another developer's
interface. With this pattern, only a public API is returned, keeping
everything else within the closure private.
Please have a look below code:
for(var i=0; i< 5; i++){
setTimeout(function(){
console.log(i);
},1000);
}
Here what will be output? 0,1,2,3,4 not that will be 5,5,5,5,5 because of closure
So how it will solve? Answer is below:
for(var i=0; i< 5; i++){
(function(j){ //using IIFE
setTimeout(function(){
console.log(j);
},1000);
})(i);
}
Let me simple explain, when a function created nothing happen until it called so for loop in 1st code called 5 times but not called immediately so when it called i.e after 1 second and also this is asynchronous so before this for loop finished and store value 5 in var i and finally execute setTimeout function five time and print 5,5,5,5,5
Here how it solve using IIFE i.e Immediate Invoking Function Expression
(function(j){ //i is passed here
setTimeout(function(){
console.log(j);
},1000);
})(i); //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4
For more, please understand execution context to understand closure.
- There is one more solution to solve this using let (ES6 feature) but under the hood above function is worked
for(let i=0; i< 5; i++){
setTimeout(function(){
console.log(i);
},1000);
}
Output: 0,1,2,3,4

garbage collection with node.js

I was curious about how the node.js pattern of nested functions works with the garbage collector of v8.
here's a simple example
readfile("blah", function(str) {
var val = getvaluefromstr(str);
function restofprogram(val2) { ... } (val)
})
if restofprogram is long-running, doesn't that mean that str will never get garbage collected? My understanding is that with node you end up with nested functions a lot. Does this get garbage collected if restofprogram was declared outside, so str could not be in scope? Is this a recommended practice?
EDIT I didn't intend to make the problem complicated. That was just carelessness, so I've modified it.
Simple answer: if value of the str is not referenced from anywhere else (and str itself is not referenced from restofprogram) it will become unreachable as soon as the function (str) { ... } returns.
Details: V8 compiler distinguishes real local variables from so called context variables captured by a closure, shadowed by a with-statement or an eval invocation.
Local variables live on the stack and disappear as soon as function execution completes.
Context variables live in a heap allocated context structure. They disappear when the context structure dies. Important thing to note here is that context variables from the same scope live in the same structure. Let me illustrate it with an example code:
function outer () {
var x; // real local variable
var y; // context variable, referenced by inner1
var z; // context variable, referenced by inner2
function inner1 () {
// references context
use(y);
}
function inner2 () {
// references context
use(z);
}
function inner3 () { /* I am empty but I still capture context implicitly */ }
return [inner1, inner2, inner3];
}
In this example variable x will disappear as soon as outer returns but variables y and z will disappear only when both inner1, inner2 and inner3 die. This happens because y and z are allocated in the same context structure and all three closures implicitly reference this context structure (even inner3 which does not use it explicitly).
Situation gets even more complicated when you start using with-statement, try/catch-statement which on V8 contains an implicit with-statement inside catch clause or global eval.
function complication () {
var x; // context variable
function inner () { /* I am empty but I still capture context implicitly */ }
try { } catch (e) { /* contains implicit with-statement */ }
return inner;
}
In this example x will disappear only when inner dies. Because:
try/catch-contains implicit with-statement in catch clause
V8 assumes that any with-statement shadows all the locals
This forces x to become a context variable and inner captures the context so x exists until inner dies.
In general if you want to be sure that given variable does not retain some object for longer than really needed you can easily destroy this link by assigning null to that variable.
Actually your example is somewhat tricky. Was it on purpose? You seem to be masking the outer val variable with an inner lexically scoped restofprogram()'s val argument, instead of actually using it. But anyway, you're asking about str so let me ignore the trickiness of val in your example just for the sake of simplicity.
My guess would be that the str variable won't get collected before the restofprogram() function finishes, even if it doesn't use it. If the restofprogram() doesn't use str and it doesn't use eval() and new Function() then it could be safely collected but I doubt it would. This would be a tricky optimization for V8 probably not worth the trouble. If there was no eval and new Function() in the language then it would be much easier.
Now, it doesn't have to mean that it would never get collected because any event handler in a single-threaded event loop should finish almost instantly. Otherwise your whole process would be blocked and you'd have bigger problems than one useless variable in memory.
Now I wonder if you didn't mean something else than what you actually wrote in your example. The whole program in Node is just like in the browser – it just registers event callbacks that are fired asynchronously later after the main program body has already finished. Also none of the handlers are blocking so no function is actually taking any noticeable time to finish. I'm not sure if I understood what you actually meant in your question but I hope that what I've written will be helpful to understand how it all works.
Update:
After reading more info in the comments on how your program looks like I can say more.
If your program is something like:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(function (request) {
// do something
});
});
Then you can also write it like this:
readfile("blah", function (str) {
var val = getvaluefromstr(str);
// do something with val
Server.start(serverCallback);
});
function serverCallback(request) {
// do something
});
It will make the str go out of scope after Server.start() is called and will eventually get collected. Also, it will make your indentation more manageable which is not to be underestimated for more complex programs.
As for the val you might make it a global variable in this case which would greatly simplify your code. Of course you don't have to, you can wrestle with closures, but in this case making val global or making it live in an outer scope common for both the readfile callback and for the serverCallback function seems like the most straightforward solution.
Remember that everywhere when you can use an anonymous function you can also use a named function, and with those you can choose in which scope do you want them to live.
My guess is that str will NOT be garbage collected because it can be used by restofprogram().
Yes, and str should get GCed if restofprogram was declared outside, except, if you do something like this:
function restofprogram(val) { ... }
readfile("blah", function(str) {
var val = getvaluefromstr(str);
restofprogram(val, str);
});
Or if getvaluefromstr is declared as something like this:
function getvaluefromstr(str) {
return {
orig: str,
some_funky_stuff: 23
};
}
Follow-up-question: Does v8 do just plain'ol GC or does it do a combination of GC and ref. counting (like python?)

Categories

Resources