This is the 10th day of my participation in the August Text Challenge.More challenges in August

Understand closures from a memory perspective

Data of primitive types in scope is stored in stack space, and reference types are stored in heap space.

lead

Function foo() {var myName = "geeky time" let test1 = 1 const test2 = 2 var innerBar = {setName:function(newName){myName = newName }, GetName :function(){console.log(test1) return myName}} return innerBar} var bar = foo() bar.setName(" geeky ") bar.getName() console.log(bar.getName())Copy the code

First check the execution process

  1. The global execution context is first created and pushed onto the call stack

    • Global execution context

      • Bar = undefined foo()…
      • Lexical context: empty
  2. Execute foo to give the innerBar returned to bar

    1. The foo function is first compiled before execution. Create an empty execution context.

    2. The JavaScript engine performs a lexical scan of the inner function, starting with the setName function, and finds that the inner function refers to the myName of the foo function. Since the inner function refers to the variable of the outer function, the JavaScript engine determines that this is a closure. So a “closure(foo)” object is created in the heap space (this is an internal object that JavaScript cannot access).

    3. Closure (foo) : test1; closure(foo) : test1; closure(foo) : test1; closure(foo); The “closure(foo)” object in the heap contains the myName and test1 variables.

    4. Because test2 is not referenced by an internal function, test2 remains in the lexical context of foo’s execution on the call stack.

      The execution context of foo at this point

    5. When the return returns innerBar, Foo’s execution context pops out of the call stack, but since the innerBar of the returned object has a reference to its parent scope, the closure(foo) is created and remains in the heap.

  1. So when the implementation toBar.setname (" Geekbang "); bar.getName();You can still access the properties in the closure(foo) object.

conclusion

There are two core steps to generating closures: the first step is to pre-scan the internal functions; The second step is to save the external variables referenced by the inner function to the heap.