First, scope

Any programming language has the concept of scope. Simply put, scope is the accessible scope of variables and functions, that is, scope controls the visibility and life cycle of variables and functions. In JavaScript, variables are scoped globally and locally.

1. Global Scope

Objects that can be accessed anywhere in the code have a global scope. Generally speaking, there are several cases that have a global scope:

(1) Outermost functions and variables defined outside of outermost functions have global scopes, such as:

var globalValue = `global value`;

function checkGlobal() {
    var localValue = `local value`;
    console.log(localValue);                // "local value"
    console.log(globalValue);               // "global value"
}

console.log(globalValue);                   // "global value"
console.log(checkGlobal);                   // "global value"
console.log(localValue);                    // "Uncaught ReferenceError: localValue is not defined"
Copy the code

(2) All variables that do not have a direct assignment are automatically declared as global scopes, for example:

function checkGlobal() {
    var localValue = 'local value';
    globalValue = 'global value';
    console.log(localValue, globalValue);    // 'local value' 'globalValue'
}

console.log(globalValue);                    // 'globalValue'
console.log(localValue);                     // "Uncaught ReferenceError: localValue is not defined"
Copy the code

(3) Properties of all Window objects

In general, the built-in properties of a window object have a global scope, such as window.name, window.location, window.top, and so on.

2. Local Scope

In contrast to global scopes, local scopes are generally accessible only within fixed snippets of code.

(1) Function scope

That’s the variable declared inside the function,

(2) block-level scope

Block-level scopes can be declared by lets and const, and the declared variables specify that they are not accessible outside the block-level scope.

Lexical scope and dynamic scope

(1) Lexical scope

Lexical scope is also static, and is used in JavaScript. Lexical scope is the scope of the definition at the lexical stage. A piece of code that has its scope defined before it is executed, simply defined before execution where it can apply its scope (variable). In other words, the lexical scope is determined by where you write the variable and block scope when you write the code. So lexers keep their scope constant when they process code (most of the time) such as:

var a = 1;

function foo() {
    console.log(a);
}

function bar() {
    var a = 2;
    foo();
}

bar();      //  1
Copy the code
(2) Dynamic scope

Dynamic scope is the opposite of lexical scope.

It can be known from the above examples:

It still executes the function as if it were lexically scoped, except that when foo() is executed, it does not look for a one level up, but from the scope of the calling function, so the final output is 2.

Scope chain

In JavaScript, functions are also objects, and in fact, everything in JavaScript is an object. Function objects, like any other object, have properties that can be accessed through code and a set of internal properties that are only accessible to the JavaScript engine. One of these internal properties is [[Scope], defined by ecMA-262 standard version 3. This internal property contains the set of objects in the Scope of the function being created. This set is called the function’s Scope chain, and it determines what data can be accessed by the function.

In layman’s terms, when the desired variable cannot be found in its scope, it will look up the desired variable layer by layer until it finds the global scope and gives up the search. This layer by layer relationship is the scope chain.

Third, the closure

Closures occur when a function can remember and access its lexical scope. Even if the function is executed outside the current lexical scope.

function foo() {
    var a = 1;
    return function() {
        console.log(a); }}var bar = foo();
bar();
Copy the code

As you can see from the code above, the result of the foo() function is returned to bar, while the variable a is still in use and thus not destroyed, and then the bar() function is executed. In this way, we can access variables in the function’s inner scope from the outer scope. This is the closure.

Closure formation conditions:

  • Nested function
  • An inner function refers to a local variable of an outer function

What closures do:

  • You can read variables inside a function
  • The value of a variable can be kept in memory for a long time with a long life cycle.
  • Can be used to implementJSModule (JQueryLibrary, etc.)

JS module is a JS file with specific functions, all the data and functions are encapsulated in a function inside (private), only to expose an object or function containing multiple methods to the outside, the user of the module, only through the object exposed by the module to call the method to achieve the corresponding function.

Closure features:

  • Every function is a closure, and a function can remember the scope in which it was defined, and where the function goes, the scope goes when it was defined.
  • A memory leak

A memory leak is an object that exists when you don’t need it. So you can’t abuse closures. When we are done with the closure, we should set the reference variable to NULL.

function outer(){
    var num = 0;
    return function add(){
        num++;
        console.log(num);
    };
 }
var func1 = outer();
func1();              / / 1
func1();              // 2 [not released, always occupied]
var func2 = outer();
func2();              // 1 [The closure is new when the function is rereferenced]
func2();              / / 2

Copy the code

Interviewer: Talk about scopes and closures