If you go to Baidu for the question “JavaScript variable storage mechanism”, you will see many answers: for primitive types, the data itself is stored on the stack, for object types, the stack is only a reference to the heap address.

So is this really the case? What is the storage structure of heap and stack mentioned in the answer? Let’s look at them one by one

The stack and heap

To understand JavaScript’s variable storage mechanism, we must first understand the concept and characteristics of the heap and stack.

The heap

Think of the heap as a large memory storage space in which you can store any type of data. However, this space is private, and the operating system does not care what is stored in it, nor does it take the initiative to clean up its contents. Therefore, in C, programmers need to manually manage the memory to avoid memory leaks that affect performance.

However, some high-level languages such as JAVA have the concept of garbage collection (GC), which is used to help programs manage memory space and automatically clean up data that is no longer used in the heap.

Data that can’t be stored in the stack like an object is stored in the heap, where the object’s address in the heap is kept, which is a reference to the object. So we’re talking about stacks so what is a stack?

The stack

A stack is a linear structure in memory used to store local variables and function parameters, following the principle of first in, last out. Data can only be pushed sequentially and removed sequentially. Of course, the stack is just a formal description of a contiguous area of memory, and the operation of moving data onto and off the stack is just the movement of the stack pointer up and down the memory address. As shown below:

As shown in the figure, the stack pointer starts to point to 0x001 in memory, and the add function starts to call. Since two variables have been declared and two values have been added to the stack, the stack pointer also starts to move. When the add function ends, it just moves the stack pointer down. But the next assignment will overwrite it.

However, it should be noted that the data in the stack area in memory will be automatically removed from the stack after the function call ends, and the operating system will automatically reclaim the data without the operation of the program. That is, the variables in the stack will disappear after the function call ends. This is also the nature of the stack: no manual management, light weight, function creation at the end of the call, disappear.

JS variable storage mechanism and closure

Figure out the way and the characteristics of stack and heap to store data, so for the variable storage mechanisms result in JS: for primitive types, the data itself exists within the stack, the object type, put in the stack is just a pile of the inside address references Should be logical, but we all know that exist in the js closure, the concept of the so-called closed package refers to:

A combination of a function bound to (or surrounded by) references to its surrounding state (lexical environment) is a closure. That is, closures allow you to access the scope of an outer function within an inner function. In JavaScript, whenever a function is created, the closure is created at the same time the function is created. (Quoted from MDN)

Since stack data is destroyed at the end of function execution, how does a function closure work in JavaScript? Take a look at the following code

function sum () {
    let i = 0;
    return function () {
        i++;
        returni; }}let sumFun = sum();
sumFun(); / / 1
sumFun(); / / 2
Copy the code

If I is created when sum is called, it is popped from the stack when retun ends, and the variable I is destroyed. So why does a call to sumFun output 1?

So in the above example, where closures exist, the variables are not stored on the stack, but should be stored in the heap for use by sumFun. To understand this, we need to take a closer look at the different types of variables in JavaScript, and how they are stored differently.

JavaScript variable storage

Before we look at the three types, let’s take a look at JavaScript variable storage as an example

function testScope () {
    let num = 1;
    let string = 'string';
    let bool = true;
    let obj = {
        attr1: 2.attr2: 'string'.attr3: false.attr4: 'attr4'
    }
    return function scopeFun() {
        console.log(num, string, bool, obj); }}Copy the code

With the testScope call, to ensure that the variable is not destroyed, create an object in the heap calledScopeLet’s say the variable is thetaScopeThe attributes of the. The data structure in the heap looks roughly like this:

That would solve the closure problem becauseScopeObjects are stored in the heap and therefore returnedscopeFunYou can have a functionScopeObject access. Here’s what this code looks like in Chrome:

The above result also reflects that JavaScript variables are not stored in the stack, but in the heap, with a special object (Scope).

So how exactly are variables stored in JavaScript processes? This is directly tied to the type of the variable, so let’s look at the type of the variable in JavaScript.

Local variables, global variables, captured variables

A local variable

Local variable: An object declared in a function that is not used by other scopes after the function returns. All local* in the following code are local variables.

function testLocal () {
    let local1 = 1;
    var local2 = 'str';
    const local3 = true;
    let local4 = {a: 1};
}
Copy the code

Look at theChromeResults of execution in

The global variable

The global variable is window in the browser and global in Node. The global variable is added by default to the lower end of the function scope chain, which is the last one in the function [[Scopes]] above. Look at the last one in the Scopes example above.

Global variables need special attention: var and let/const are different.

var

The global var variable simply adds a property to the global object.

var testVar = 1;
/ / is equivalent to
windows.testVar = 1;
Copy the code

let / const

The global let/const variable does not modify the Window object, but puts the variable declaration under a special object (similar to Scope).

let testLet = 1;
console.dir(() = > {})
Copy the code

In the followingChromeResults of execution in

Captured variable

A captured variable is the opposite of a local variable: declared in a function but used by an unexecuted scope (function or class) after the function returns. Catch * in the following code are all captured variables.

function testCatch1 () {
    let catch1 = 1;
    var catch2 = 'str';
    const catch3 = true;
    let catch4 = {a: 1};
    return function () {
        console.log(catch1, catch2, catch3, catch4)
    }
}

function testCatch2 () {
    let catch1 = 1;
    let catch2 = 'str';
    let catch3 = true;
    var catch4 = {a: 1};
    return class {
        constructor(){
            console.log(catch1, catch2, catch3, catch4)
        }
    }
}
console.dir(testCatch1())
console.dir(testCatch2())
Copy the code

Look at theChromeResults of execution in

Storage of variables

This should make it clear: everything except local variables is stored in the heap. According to the data type of the variable, it can be divided into the following two situations:

  • If it’s a base type, the stack stores the data itself.
  • If it is an object type, the stack stores references to objects in the heap.

So how does a JavaScript parser determine if a variable is local? Determines whether it is referenced by an internal function, and if the JavaScript parser doesn’t, stores it on the heap. Execute the following code in the next step

function test () {
    let num1 = 1;
    var num2 = 2;
   return function() {
       console.log(num1)
   }
}
console.dir(test())
Copy the code

You can seeScopesThere are only variables innum1

Assignment of a variable

Whether a variable is stored on a stack or in a heap (in memory anyway), its structure is similar to that of a value:

Ok, now let’s look at assignment. There are two ways to assign depending on the type of the variable to the right of the = sign:

Assign a constant

1, “string”, true, {a: 1} are all constants. These values cannot be changed once they are declared. Some people may be stubborn.

The following code:let foo = 1;JavaScript declares a variable foo and sets its value to 1

If a bar variable is declared:let bar = 2;, the memory will look like this:

What if we’re declaring an object?

let obj = {
    a: 1.b: 2
}
Copy the code

If obj.foo = 3, it will actually change the memory area 0x1021, but the memory address obj points to will not change.

Assign to a variable

Foo, bar, and obj in the above procedure are all variables, and variables represent a reference relationship whose value is not determined.

If I assign the value of one variable to another, for example:let x = foo;You simply refer x to the same address value as foo, and no new memory space is used. As shown in the figure below

Mechanism of const

Const is a way of declaring a variable new to ES6. Variables decorated with const cannot be changed. In JavaScript’s variable store diagram, the memory address that a variable points to cannot change. That arrow can’t be changed.

For example, execute the following code

const foo = 'lxm';
foo = 'lxm love js'; // Uncaught TypeError: Assignment to constant variable.
Copy the code

What if you define an object of const type and modify its properties?

const obj = {
    a: 1.b: 2
};
obj.a = 2;
Copy the code

The address referenced by obj does not change. The change is in the heap corresponding to obj, as shown in the figure below

Ok, so by this point it should be pretty clear what the problem is

In JavaScript, variables don’t exist entirely on the stack. Early JavaScript compilers even stored all variables in a single object called a closure. JavaScript is a function-based language, where functions change infinitely. Therefore, using the stack does not solve the language problem, and the heap is convenient to store various types of variables. This should help you understand JavaScript’s variable storage mechanism. Write wrong still please criticize correct ~ 😊