0

Before asking my question let me give you some information. See this piece of code

"use strict"

function outer() {

    let counter = 0;

    function incrementCounter() {   
        counter++;
        console.log(counter);
    }

    return incrementCounter;
}

const newFunction = outer();  // A 
newFunction();                // B
newFunction();                // C

This is an example of closure. When the line A done. The global memory seems like this:

                   Global     Memory
________________________________________________________________

                           
Function Name                                           Data

outer            ---------------------------->    { outer function code }
                                                        
                                                       
newFunction      ---------------------------->    { incrementCounter's code / definitions / functionalty }                                     
                                                  | live data attached to incrementCounter | 
                                                  | counter = 0 }                          |

The live data section includes counter variable.

When we run the function on line B and when engine encounter counter++ first it looks new Function's local memory for find counter variable then if don't find, it checks the live data mentioned above.

When it finally find the counter inside of live data, counter++ works. The same things are repeated for the line C.

At the end of all this, we see 1 and 2 on the console.

Now Check out this piece of code.

"use strict"

function outer() {

    let counter = 0;

    function incrementCounter() {   
        counter++;
        console.log(counter);
    }

    return incrementCounter;
}

const newFunction = outer();  // A 
newFunction();                // B
newFunction();                // C


const anotherFunction = outer(); // D 
anotherFunction();               // F
anotherFunction();               // G

When we run the above code, we see 1 2 1 2 on the console. Not 1 2 3 4. Because i know newFunction's live data field or closure or backpack is different than anotherFunction's.

Here is my questions:

1)What does global memory looks like in this case?

Does it looks like this?

                   Global     Memory
________________________________________________________________

                           
Function Name                                           Data

outer            ---------------------------->    { outer function code }
                                                        
                                                       
newFunction      ---------------------------->    { incrementCounter's code / definitions / functionalty }                                     
                                                  | live data attached to incrementCounter | 
                                                  | counter = 2 }                          |

anotherFunction  ---------------------------->    { incrementCounter's code / definitions / functionalty }                                     
                                                  | live data attached to incrementCounter | 
                                                  | counter = 2 }                          |

Or does it looks like this?

                   Global     Memory
________________________________________________________________

                           
Function Name                                           Data

outer            ---------------------------->    { outer function code }
                                                        
                                                  |                Unique                  |
newFunction      ---------------------------->    | live data attached to incrementCounter | 
                 |                                | counter = 2 }                          |       
                 |                
                 | common function definition                 
                 |----------------------->        { incrementCounter's code / definitions / functionalty }  
                 |                                         
                 |                                |                Unique                  |    
anotherFunction  --------------------------->     | live data attached to incrementCounter | 
                                                  | counter = 2 }                          |  

2)Is there just one outer function in global memory or more?

3)In global memory Is there are one function definition of incrementCounter or is there are two function definition?

UPDATE

I think i should add my resource here. I learned the things I mentioned above while watching codesmith's javascript the hard parts video series.

If you can check this video maybe you can understand this question better.

  • What doe you mean by global memory? Do you mean having global scope? – Nike Lepz Jan 26 '21 at 02:04
  • @DipeshTimilsina No. I think global memory and global scope different things from each other. When you define a variable in global scope it will stored in global memory but when you define a variable inside of function, inside of it's local scope( function's scope) it will stored in the function's temporary local memory. I hope I was able to explain myself. – Mesut Çiftçi Jan 26 '21 at 02:17
  • then aren't they probably the same ? :) – Nike Lepz Jan 26 '21 at 02:18
  • I think the answer to your question would be that yes there is one definition of outer function in the global memory, and no definition of increment function in the global memory. Because it's inside a function. Each function call means a new scope for the inner function to work on. So the global memory would look like the first one you showed. i,e there will a new incrementCounter function for each instance of the outer function. – Nike Lepz Jan 26 '21 at 02:24
  • @DipeshTimilsina Actually, after executing line A or D, the incrementCounter function is moved from inside of outer function's local memory to global memory. So I'm not sure if your answer is right or wrong. This part is confusing me. – Mesut Çiftçi Jan 26 '21 at 02:38
  • @then Idk man. I guess I have to look into it too. – Nike Lepz Jan 26 '21 at 02:43
  • You don't need to keep the code and the variables in the same area of memory. Indeed most modern Intel and AMD CPUs discourages this by having a noexec bit to mark pages non-executable. The code can indeed be compiled only once and have only one copy. But the variables may occupy different memory locations. This is not javascript specific but is normal for even C/C++ etc. – slebetman Jan 26 '21 at 03:23
  • Check out my answer to this other question: https://stackoverflow.com/questions/26061856/javascript-cant-access-private-properties/26063201#26063201. Does it provide an answer to you? Is there anything else you're confused about? – slebetman Jan 26 '21 at 03:25
  • @slebetman I checking your answer. I am asking for clarification: I know the term call stack. When we run a function, the function is added to the bottom of the call stack. Then if the function is done just popped out from call stack. Whenever a function is executed, an execution context is created for that function. So the execution context have two parts. One part is a thing that runs function code other part is a local temporary memory for function. When the function popped out from call stack the execution context removed so the local memory also deleted. +++ – Mesut Çiftçi Jan 26 '21 at 06:57
  • @slebetman Are we explain same things used different term? – Mesut Çiftçi Jan 26 '21 at 06:57
  • @slebetman Another question. You said "The code can indeed be compiled only once and have only one copy. But the variables may occupy different memory locations." Can you review the second figure in my first question? What do you think about this. Can we say there is only one incrementCounter's code and the live data is there somewhere in ram? – Mesut Çiftçi Jan 26 '21 at 07:09
  • 1
    You're kind of mixing two different concepts. When the interpreter first parses the entire script into bytecode (think of it as instructions for a virtual CPU called javascript). Some of these bytecodes if executed a lot will later get compiled into native CPU instructions automatically. These bytecodes and program instructions need to be stored somewhere. They are stored in RAM of course but they are normally treated as unmodifiable by javascript. This is normally called the TEXT segment or CODE segment. This does not contain variables, only constants and instructions that create variables. – slebetman Jan 26 '21 at 07:41
  • 1
    ... now, when the interpreter executes javascript (or indeed when the CPU executes programs in general) it reads this text section to fetch instructions to execute. When it finds an instruction that says something like `x = 1` it will need to allocate memory. But remember, the memory that holds the instructions (functions) have already been allocated. It is the instructions themselves now requesting for memory to store a variable. THIS is the level you are thinking.. the level of variables. Scope is nothing more than rules that instructions follow for accessing variables. – slebetman Jan 26 '21 at 07:44
  • 1
    ... When you do `a = function () {...}` the function already exist. Say for example the function was compiled and now exist at RAM address 0x1234. The expression `a = function () {..}` only needs to store the value 0x1234 into the variable a which may be exist at RAM location 0x5678. So if you look at RAM and look at where the variable `a` is you will not see the function you will only see a pointer (reference) to the function. The function already exist long before the variable `a` was created – slebetman Jan 26 '21 at 07:47

0 Answers0