Full summer vacation how little reading, hereby leave a learning footprint

Essential knowledge concepts

We all know that there is an important concept in JavaScript called an execution environment. What is an execution environment?

The execution environment defines other data that variables or functions have access to, and determines their respective behavior. Each execution environment has a variable object associated with it, and all variables and functions defined in the environment are stored in this object.

What you mean? Simply put, variables and functions that you define are boxed in an environment that prevents you from doing illegal things. Just like you define variable A in function A, you can’t use variable A in function B

    function A() {
        var a = 1;
    }
    function B() {
        console.log(a);
    }
    B(); 
Copy the code

Function A is defined in function A’s execution environment, and function B’s execution environment cannot access A. Note that when all code in the execution environment is finished, the environment is automatically destroyed, along with all variables and function definitions stored in it

Let’s take a look at what JavaScript does

We know that each function has its own execution environment, and when the execution stream enters a function, the function’s environment is pushed into an environment stack. After the function is executed, the stack pops up its environment, returning control to the previous execution environment

So let’s pick up where we left off, is there any way that function B can access A variable in function A. Let’s look at this example

    A();
    var a = 2;
    function A() {
        var a = 1;
        B(); 
        function B() {
            console.log(a); }}Copy the code

And then somebody said, “That’s it, that’s it?”

Hahaha, hold on, I want to talk about scope chains

The scope chain

Remember when I introduced the execution environment, I said that each execution environment has a variable object associated with it, and if the environment is a function, the active object is the variable object.

Scope chain is essentially a pointer to the variable object list, this example performs printing variable a this statement, identifier resolution along the search scope chain level level, when he found that the function of B in the execution environment live objects without variable a, went to the primary function of a execution environment of active objects, bingo! Found it. That’s why the console prints 1 instead of 2, right

Without further ado, let’s get right to the picture

In this example, the rectangles with different background colors represent an execution environment. It is worth mentioning that in Web browsers, the global execution environment is considered a Window object because all global variables and functions are created as properties and methods of the Window object.

Did anyone notice that in that example I called function A first and then defined it?

This is function declaration promotion

There are two ways to define a function: one is a function declaration, and the other is a function expression

The first is this:

function fn (arg0,arg1){
    / / the function body
}
Copy the code

The second is this:

var fn = function(arg0,arg1){
    / / the function body
}
Copy the code

An important feature of function declarations is function declaration promotion, which means that they are read before the code is executed. This means we can put a function declaration after the statement that calls it as in the previous example.

If you are interested, you can write them in functional expressions. I therefore think there will be an error, so I therefore pay more than I pay.

About the closure

Closures are functions that have access to variables in the scope of another function

Closures are actually quite simple, and we actually created A closure in the last example, where function B accesses variable A in function A.

Consider the following code

    function createComparisonFunction(propertyName){
        return function (object1,object2) {
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
            if(value1 < value2){
                return -1;
            } else if(value1 > value2){
                return 1;
            } else {
                return 0; }}}// Create a function
    var compareNames = createComparisonFunction("number");

    // Call the function
    var result = compareNames({ number: "15" }, { number: "12" });
    console.log(result);
    
    // Dereference anonymous functions (to free memory)
    compareNames = null;
    
    
Copy the code

The compareNames function is able to access all variables defined in createComparisonFunction, although this example only accesses propertyName. Ever wonder why? The reason is that after the createComparisonFunction line is executed, there is a chain of scope that createComparisonFunction’s active object -> Window global object, and interestingly, when createComparisonFunction returns, its execution environment is destroyed. But its live object remains in memory because the anonymous function’s chain of scopes still references the live object. Why live objects remain in memory is a matter of JavaScript’s garbage collection mechanism, which I won’t go into detail here.

Why is there no active object for this anonymous function? I think it is because this anonymous function has not been called yet, so it is not pushed into the environment stack, and no execution environment is generated.

Consider the following example and give your answer

function createFunctions() {
        var result = new Array(a);for (var i = 0; i < 10; i++) {
            result[i] = function () {
                returni; }}return result;
    }
    console.log(createFunctions()[0] ());Copy the code

Is there anyone who thinks 0 as I do

Well, congratulations on falling for HHH. The answer is 10

The function createFunctions returns an array. Each item in the array is an anonymous function that returns the variable I defined in createFunctions. CreateFunctions ()[0] is an anonymous function that holds the live object of createFunctions, so each entry in the array refers to the same variable I.

Disadvantages of closures

  • Memory footprint

Because closures carry the scope of the function that contains them, they take up more memory than other functions. Overuse of closures can lead to excessive memory usage, so try not to use closures if you can’t use them in development

  • A memory leak

A memory leak is a waste of memory that is no longer used due to negligence or error

Closures hold local variables of the containing function, leaving them unreleased and causing a memory leak

function fn() {
        var element = document.getElementById("xxx");
        element.onclick = function () {
            console.log(element);
            // The function body references local variables in fn}}Copy the code

The solution is simple: Element = NULL touches the reference to the DOM object, ensuring that it is properly reclaimed

Private variables

Any variable defined in a function can be considered private and can be accessed through closures.

We call public methods that have access to private variables and functions privileged methods

function fn() {
        // Private variables
        var str = 'hello world';

        // Privileged methods
        this.publicMethod = function () {
            return str
        }
    }
    var func = new fn();
    console.log(func.publicMethod());
Copy the code

use

Prevents naming conflicts caused by too many global variables and functions

The last

If you have any questions and deficiencies, please point out in the comments section.