function myClass()
{
//lots and lots of vars and code here.
this.bar = function()
{
//do something with the numerous enclosed myClass vars
}
this.foo = function()
{
alert('Hello'); //don't do anything with the enclosed variables.
}
}
Each instance of myClass gets its own copy of bar and foo, which is why prototyped methods use less memory. However, I would like to know more about the memory use of inner methods.
It seems obvious to me that (1) below must be true. Do you agree?
Now (2) is the question I'm really after.
This will depend entirely on the implementation not the language. Naive implementations will keep far more around than others. Any answer that is true for e.g. V8 (chrome's JS engine) may not be true for Spidermonkey (Firefox's) or JScript (IE) etc...
In my experience (this is definitely how GHC handles closures), the actual code of the functions (inner or outer) only exists once, but an "environment" mapping variables to values must be kept around for the closure (bar), so no, I wouldn't expect the JS implementation to keep around more than one copy of MyClass, but it will keep around a copy of its environment at least with this.bar, sensible implementations might realize that no environment is actually needed foo is not actually a closure, and thus does not need to keep a copy of the environment from the call to MyClass however do not rely on this behaviour.
Especially since the behavior of JS's eval function which evaluates a string in the same lexical environemnt as the eval call, it is quite likely that JS implementations always keep the lexical environment around.
I'm reasonably certain that any function has the a pointer to the entire state. It's irrelevant whether it references any variables it still has access to them.
Of course you do release that both bar & foo point to the same "entire state" of the object. So it doesn't take any more memory. I guess you have to allocate one more pointer internally so you can point to the "entire state" of the object but optimising for something like that is silly.
Whether it optimises it away is javascript engine specific. By all means read the chromium source and find out.
I'll see if I can dig some quotes out of the spec for you.
Entering Function code from the spec:
10.4.3 Entering Function Code The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:
- If the function code is strict code, set the ThisBinding to thisArg.
- Else if thisArg is null or undefined, set the ThisBinding to the global object.
- Else if Type(thisArg) is not Object, set the ThisBinding to ToObject(thisArg).
- Else set the ThisBinding to thisArg.
- Let localEnv be the result of calling NewDeclarativeEnvironment passing the value of the [[Scope]] internal property of F as the argument.
- Set the LexicalEnvironment to localEnv.
- Set the VariableEnvironment to localEnv.
That tracks your environment to NewDeclarativeEnvironment.
NewDeclarativeEnvironment
10.2.2.2 NewDeclarativeEnvironment (E) When the abstract operation NewDeclarativeEnvironment is called with either a Lexical Environment or null as argument E the following steps are performed:
- Let env be a new Lexical Environment.
- Let envRec be a new declarative environment record containing no bindings.
- Set env’s environment record to be envRec.
- Set the outer lexical environment reference of env to E.
- Return env.
This tracks your environment to E which is the [[Scope]] of the function Object
13.2 Creating Function Objects Given an optional parameter list specified by FormalParameterList, a body specified by FunctionBody, a Lexical Environment specified by Scope, and a Boolean flag Strict, a Function object is constructed as follows:
- Create a new native ECMAScript object and let F be that object.
- Set all the internal methods, except for [[Get]], of F as described in 8.12.
- Set the [[Class]] internal property of F to "Function".
- Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
- Set the [[Get]] internal property of F as described in 15.3.5.4.
- Set the [[Call]] internal property of F as described in 13.2.1.
- Set the [[Construct]] internal property of F as described in 13.2.2.
- Set the [[HasInstance]] internal property of F as described in 15.3.5.3.
- Set the [[Scope]] internal property of F to the value of Scope.
- Let names be a List containing, in left to right textual or
Turn's out the spec is just telling you things you already know. Every functions contain the Scope. As the other poster mentioned it is upto individual implementation to "optimise" some of the scope away in terms of memory management.
If you ask me you really don't care about this unless you have >million instances of these objects.
The following block from the spec is more applicable:
The outer environment reference is used to model the logical nesting of Lexical Environment values. The outer reference of a (inner) Lexical Environment is a reference to the Lexical Environment that logically surrounds the inner Lexical Environment. An outer Lexical Environment may, of course, have its own outer Lexical Environment. A Lexical Environment may serve as the outer environment for multiple inner Lexical Environments. For example, if a FunctionDeclaration contains two nested FunctionDeclarations then the Lexical Environments of each of the nested functions will have as their outer Lexical Environment the Lexical Environment of the current execution of the surrounding function.
The two nested functions both have the same reference to the outer Lexical Environment
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With