JavaScript Learning -4- Variables, scopes, and memory

4.1 Original and Reference Values

ECMPScript variables can contain two different types of data: raw values and reference values

  • Primitive values are the simplest data: undefined, Null, Boolean, Number, String, and Symbol. Primitive values are accessed by value, and we operate on the actual values stored in variables
  • A reference value is an object made up of multiple values; When you manipulate an object, you’re actually manipulating a reference to the object rather than the actual object itself; Variables that hold reference values are accessed by reference

4.1.1 Dynamic Properties

  • Raw values cannot have attributes, although attempts to add attributes to raw values do not generate an error

4.1.2 duplicate values

  • The original values are copied independently of each other

    let num1 = 5;
    let num2 = num1; Num1 and NUM2 are independent of each other
    Copy the code
  • A copy of a reference value is actually a copy of a pointer. Both Pointers refer to the same object, so modifying an object through two references affects each other

4.1.3 Passing Parameters

  • Arguments to all functions are passed by value
  • The arguments to a function are local variables

4.1.4 Determine the type

  • Typeof can be used to check if it is a function

  • Typeof is useful for raw values, but not for reference values

  • Do you use the instanceof operator when you need to know what type of object it is

    colors instanceof Array
    Copy the code

4.2 Execution context and scope

  • The context of variables or functions determines which data they can access and how they behave
  • Each context has an associated variable object on which all variables and functions defined in that context reside
  • Global context: The global context is the outermost context, and depending on the hosting environment (browser), the object representing the global context may be different (window object)
  • throughvarThe defined global variables and functions become properties and methods of the window object, however, usingletandconstTop-level declarations are not defined in a global context
  • Context destruction: A context is destroyed after all of its code has been executed, including all variables and functions defined on it. The global context is not destroyed until the application exits, such as closing the web page or exiting the browser
  • Each function call has its own context, which is pushed into a context stack when code execution flows into the function. After the function completes execution, the context stack pops the function context, returning control to the previous execution context
  • When code in a context executes, it creates a chain of scopes for variable objects, which determines the order in which code at each level of context accesses variables and functions
  • The variable object of the context in which the code is executing is always at the front of the scope chain, and if the context is a function, its active object is used as the variable object
  • When a variable or function is found, it is searched up the scope chain until the variable object that found the global context stops; The variable object of the global context is always the last variable object of the scope

4.2.1 Scope chain enhancement

Some statements cause a temporary context to be added to the front of the scope chain, which is removed after code execution. This occurs in two general cases:

  • try/catchThe statementcatchStatement: a new variable object is created that contains the declaration of the error object to be thrown
  • withStatement: adds the specified object to the front of the scope chain

4.2.2 Variable declaration

4.2.2.1 usevarThe function scope declaration of

  • In the use ofvarWhen a variable is declared, it is automatically added to the nearest context; In a function, the closest context is the local context of the function

4.2.2.2 useletBlock-level scope of

  • letIs block-level in scope
  • The block-level scope consists of the nearest pair containing curly braces{}Define; In other words,ifBlock,whileBlock,functionBlocks, even individual blocksletDeclare the scope of a variable
  • letYou cannot declare twice in the same scope
  • letSuitable for use inforLoop through, usingvarDeclared iteration variables leak out of the loop
  • letVariables cannot be used before declaration

4.2.2.3 useconstConstant declaration of

  • It is recommended to useconst

4.2.2.4 Finding Identifiers

  • Search along the scope chain until the variable object in the global context is found or the search stops when an identifier is found

4.3 Garbage Collection

  • JavaScript implements memory allocation and idle resource reclamation through automatic management
  • The basic idea: The process of determining which variable is no longer needed, and then releasing the memory it occupies, is periodic, meaning that the garbage collector runs automatically at certain intervals (or at a predetermined collection time during code execution)
  • How do you determine which variable is still useful and which variable is not? There are two main strategies for marking unused variables: tag cleaning and reference counting

4.3.1 Mark cleaning – Recommended

  • When a variable is entered into the context, such as declaring a variable inside a function, it is marked as existing in the context
  • Variables are also marked out of context when they are out of context
  • Ways to mark variables: either a flag bit or to maintain a list

4.3.2 Reference Counting

  • For each value, count the number of times it is referenced. When you declare a variable and assign a reference value to it, the value is referenced 1. If the same value is assigned to another variable, the number of references is increased by one

  • If the variable holding a reference to that value is overwritten by another value, the number of references is reduced by one

  • When the number of references to a value is zero, there is no way to access the value, so memory can be reclaimed

  • Problem: circular reference, object A has A pointer to object B, and object B also references object A

    function Problem() {
      let objectA = new Object(a);let objectB = new Object(a); objectA.someOtherObject = ObjectB; objectB.anotherObject = ObjectA; }Copy the code

    Both objectA and objectB have a reference count of 2. When the function ends, both objectA and objectB are out of scope, but according to reference counting rules, the reference count of objectA and objectB becomes 1 and never goes to 0. ObjectA and objectB are never recycled, causing a memory leak

4.3.3 performance

The garbage collector runs periodically and can cause a performance penalty if many variables are allocated in memory. So when is it important to call the garbage collector

  • After a full garbage collection, V8’s heap growth strategy determines when to recycle again based on the number of active objects plus some margin
  • IE6: The number of variables, object/array literals and array slots are fixed when garbage collection is triggered
  • IE7: Dynamically changing thresholds such as allocation variables, literals, or array slots trigger garbage collection

4.3.4 Memory Management

  • If the data is no longer necessary, set it to NULL and release its reference

4.3.4.1 throughconstandletClaim to improve performance

  • constandletHaving block-level scope may allow garbage collection earlier
  • const > let > var

4.3.4.2 Hiding classes and Deleting operations

  • The V8 engine makes use of hidden classes when it compiles interpreted javascript code into actual machine code

    function Article() {
      this.title = 'aaa';
    }
    
    let a1 = new Article();
    let a2 = new Article();
    Copy the code

    At this point, the two class instances, A1 and A2, share the same hidden class because the two instances share the same constructor and stereotype

    a2.author = 'Jake';
    Copy the code

    If you add this line of code, a1 and A2 will correspond to two different hidden classes. Depending on the frequency of this operation and the size of the hidden class, performance may be affected

    Solution:

    function Article(author) {
      this.title = "aaa";
      this.author = author;
    }
    
    let a1 = new Article();
    let a2 = new Article('Jake');
    Copy the code

    A hidden class can be shared at this point, resulting in potential performance gains.

  • Using the delete keyword causes the same hidden class fragment to be generated

    function Article(author) {
      this.title = "aaa";
      this.author = author;
    }
    
    let a1 = new Article();
    let a2 = new Article('Jake');
    
    delete a2.author;
    Copy the code

    At this point, even if two instances use the same constructor, they no longer share a hidden class. Dynamically deleting attributes has the same consequences as dynamically adding attributes

    Best practice: Set unwanted attributes to NULL to keep the hidden classes intact and continue sharing

4.3.4.3 Memory Leaks

  • Scenario 1: Variable declarations are promoted to global variables without keywords
function setName() {
    name = 'jake';
}
Copy the code

The name variable is promoted to a global variable and created as an attribute of the window. Variables are not recycled as long as the program is not closed

  • Scenario 2: Timers
let name = 'Jake';
setInterval(() = > {
  console.log(name);
}, 100);
Copy the code

The name variable takes up memory as long as the timer is running

  • Scenario 3: Closures
let outer = function() {
  let name = 'Jake';
  return function() {
    returnname; }}Copy the code

You can’t clean up the name as long as the returned function exists, because the closure keeps referring to it, and if the name is large, it will always take up a lot of memory

4.3.4.4 Static Allocation and Object Pool

How can I reduce the number of times my browser performs garbage collection?

  • Developers can’t directly control when garbage collection starts, but can they indirectly control the conditions that trigger garbage collection
  • In theory, if you can use allocated memory wisely and avoid unwanted garbage collection, you can preserve the performance lost by freeing memory
  • One of the criteria the browser uses to decide when to garbage collect is object replacement speed
  • If many objects are initialized and then all of a sudden go out of scope, the browser will call the garbage collector to run in a more aggressive manner
  • Strategy 1: Object pool (similar to the thread pool concept) : At some point during initialization, a pool of objects can be created to manage a collection of recyclable objects. An application can request an object from the object pool, set its properties, use it, and then return it to the object pool when the operation is complete. There is no object initialization and no object replacement

4.4 summary

4.4.1 Raw and referenced Values

  • The original value has a fixed size and is stored in stack memory. Copying the original value is a copy
  • When a value is referenced, the object is stored in heap memory and the reference (pointer) is copied, not the object itself

4.4.2 typeof and instanceof

  • The typeof operator determines the original typeof a value
  • Instanceof is used to determine the reference type of the value

4.4.3 Variables and scopes

  • Any variable exists in an execution context (scope) that determines the lifetime of the variable
  • Scopes can be divided into global scopes, function scopes, and block-level scopes
  • Each time the code execution flow enters a new scope, a scope chain is created to search for variables and functions

4.4.4 Garbage collection

  • Values that leave scope are automatically marked as recyclable and then deleted during garbage collection
  • The dominant garbage collection algorithm is tag cleanup
  • Reference counting introduces the problem of circular references, which can cause memory leaks
  • Dereferencing variables not only eliminates circular references, but also helps with garbage collection, best practice