Scope and scope chain concepts

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.

  • Global scope. Objects that can be accessed anywhere in the code have a global scope. In general, the following situations have a global scope:

    • Outermost functions and variables defined outside of outermost functions have global scope;
    • All variables that are not directly assigned are automatically declared to have global scope.
    • In the browser environment, all properties of window objects have global scope;
  • Local scope, local scope is generally only in fixed code fragments can be accessed, in JS generally function scope;

Scoped chain. When code executes in an environment, it creates a scoped chain of variable objects. The scoped chain ensures orderly access to all variables and functions that the execution environment has access to. The variable object of the global execution environment is always the last object in the scope chain.

Scope rule

Scopes have a set of rules for finding variables by name.

In practice, there are usually several scopes to consider at the same time, and nesting of scopes occurs when one block or function is nested within another. Therefore, when a variable cannot be found in the current scope, the engine will continue searching in the outer nested scope until it finds the variable or reaches the outermost scope (that is, the global scope). But you cannot enter another execution environment by searching down the scope chain.

var a = 1; function f() { var a = 2; var b = 3; console.log(a); } f(); // 2 a // 1 b // An error is reportedCopy the code

Scope working model

The working model of the JS scope is lexical scope, which is defined at the lexical stage. In other words, the lexical scope is determined by where you write the variable and block scopes when you write the code, so the lexical analyzer keeps the scope the same when it processes the code (most of the time).

function f1() { console.log(a); } f1(); Function f2() {var a = 2; f1(); } var a = 1; f1(); // 1 f2(); // 1, because the scope of f1 defined by a is global a = 1, meaning that the function is called wherever it is defined based on its scopeCopy the code

In the above code, when the function executes, it looks for the desired variable first, and the scoped lookup stops when the first matching identifier is found. You can define identifiers with the same name in multiple nested scopes, which is called the “shadowing effect” (the inner identifier “overshadows” the outer identifier). Regardless of the shadowing effect, scoping searches always start at the innermost scope of the runtime and work up and out until the first matching identifier is found. Lexical scoping rules allow functions to look up variables from inside the function to the scope of the function definition, rather than from inside the function to the scope of the function when it is used. So no matter where a function is called, and no matter how it is called, its lexical scope is determined only by where the function is declared.

Function scope

There is no block-level scope in JS, but rather function-based scope. The meaning of a function scope is that all variables belonging to the function can be used and reused throughout the scope of the function (in fact, nested scopes can also be used).

function f() { if (true) { var a = 1; } console.log(a); } f(); // 1, if will not generate a new scope, so a will leak to the current function scopeCopy the code

By taking advantage of the nature of function scope, we can add a wrapper function outside any code snippet. We can “hide” internal variables and function definitions, and the outer scope cannot access anything inside the wrapper function.

var a = 1; (function f() { var a = 2; console.log( a ); // 2, wrap code with function scope so that internal variables are not accessed externally})(); console.log(a); / / 1Copy the code

Statement of ascension

var a = 1; function f() { console.log(a); Var a = 2; console.log(a); // 2 } f(); Function f() {var a; console.log(a); a = 2; console.log(a); } var a; a = 1; f();Copy the code

This process is called declarative ascension.

Declarations are raised because before JS is executed, there is a precompilation process. The precompilation stage generates variable declarations and function declarations. There is no initialization behavior (assignment).

Declare the lifting principle

Preparsing features of functions and variables:

  1. Function declarations are at the top

  2. Variable declarations are also at the top

  3. Function declarations take precedence over variable declarations :(functions are above variables)

  4. Variables and assignment statements are written together. When the JS engine parses, it will be split into declaration and assignment. Declaration is placed at the top and assignment remains in its original position

  5. Declared variables are not declared twice

    Example 1:

    conso.log(a); // function a() {} var a = 1; function a() { // }; console.log(a); Function a() {function a() {function a(); // Function declarations already have the same name, so repeated var declarations are ignored, but assignments do not console.log(a); // function a() {} a = 1; console.log(a); // 1, function declaration before variable declarationCopy the code

    Example 2:

    (function () { a = 1; alert(window.a); // undefined var a = 2; Alert (a); alert(a); alert(a); / / 2}) (); Function () {var a; // a = 1; // a = 1; // a = 1; // a = 1; // A = 1; // A = 1; alert(window.a); a = 2; alert(a); }) ();Copy the code

Spoofing function scope

There are only two types of execution environment, global and local functions, but you can trick the function scope in other ways.

  • Eval (), eval(..) in JavaScript A function can take a string as an argument, treat its contents as if they existed at that point in the program when the book was written and execute the argument code at that point. Because the eval (..) You can modify the lexical scope of write period at run time. It is not recommended because of security concerns.

    var a = 1; function f() { eval('var a = 2; '); // a in eval obscures global A, so that a in scope pops up to change console.log(a); } f(); / / 2Copy the code
  • The with statement takes an object parameter indicating the object scope of the with statement, in which all variables in the with statement are looked up. Do not use with because it affects performance.

    var a = 0; var obj = { a: 1, b: 2 }; with(obj) { a = 2; } obj. A; // 2 a //0 with(obj) { c = 3; } obj. C;} obj. C; // undefined c // 3Copy the code

More articles here, feel good hope to click a star

Write at the end:

I am just a beginner of self-study JS, notes are collected everywhere when learning, some of them are my own understanding. But a lot of knowledge comes from the big gods who share to the network, because I really do not know where to use whose article, so I can only express my thanks! There may be some mistakes in the article, if you find, please leave a message to remind me.