preface

Determined to learn Javascript again, must be completely out of the white……

Javascript is easy to learn, but actually hard to grasp. Learn according to routine, also easy to be routine, as I generally forget to learn repeatedly can not further; Finally helpless to see some big guy’s article to have an Epiphany, also just understand their previous knowledge of Javascript incredibly so shallow…… Since the knowledge came from the blog, I thought I should give it back to the blog, so I decided to document my relearning process.

The following content, I hope to have Javascript has a foundation of people have help; If you have no foundation, you should at least know about it. There are some things only in books that teachers don’t talk about.

Variables and data

What is a variable?

The simpler the questions are, the more surprising the answers are, and most people’s answers are about value; In fact, variables are the operational storage area of the program (the term memory space), and when a Javascript program is running, the storage area (the term memory space) can hold anything we need, code, data… And so on.

The data held by the variable can then be roughly divided into two types: primitive (same as primitive) and reference types; The data taken out of a variable is a value, and when you put a value into a variable, that value becomes data again.

Javascript is similar to other languages in that variables need to be declared before they can actually exist. The declared variable is called instantiation. When a value is assigned to a variable (undefined by default), it is called initialization of the variable. It’s just that this is done behind the scenes in Javascript and we don’t have to worry about it ourselves, but nonetheless, ignoring it can often lead to unexpected problems.

However, some details can be seen, such as:

let a = a ;         / / (*)
console.log(a);
// ReferenceError: can't access lexical declaration `a' before initialization
Copy the code

The perfect error (in the position of the (*) flag) indicates that the variable cannot be used without being initialized. This is different from low-level variables like C++. In fact, this phenomenon has a fancy name in Javascript: temporary dead zones, and I’ll explain why in a few chapters.

(Forgot to mention that variable declarations also need a name, the term is called identifier, I don’t think it adds or affects anything…)

However, Javascript is special in that it can automatically initialize var variables. Javascript automatically assigns undefined values to var variables. Such as:

var a = a;
console.log(a);    // undefined.
Copy the code

See, they’re all the same, but they’re all different. But it doesn’t help to think it over, as shown in the following code:

var a = a;
console.log(a+2);   // NaN
Copy the code

The result is NaN, which gets a result that we don’t want at all, and it doesn’t automatically convert to 0. If the math doesn’t work out,Javascript gives a non-numeric result, denoted by NaN. But the interesting thing is that if you use Typeof to validate NaN types:

typeof NaN ;      // number
Copy the code

It tells us that this is a number. There are a lot of things about Javascript that don’t make sense, but let’s stop messing with Javascript and start learning.

Types and Storage

Javascript has seven primitive types and one reference type, as follows:

  • The original type
    1. number
    2. string
    3. boolean
    4. symbol
    5. bigint
    6. undefined
    7. null
  • Reference type:
    1. object

(I’ll use lower case here, because typeof returns lower case.)

Along with these must know things, I don’t need to go over the specific use of other sources, after all, these things are in most sources.

However, the other thing that interests me about Typeof is that it applies to null and function results:

    function sayHello(){
     console.log('hello the world');
 }
 console.log(typeof sayHello);  // function
 console.log(typeof null);      // object
 
Copy the code

… For a function, it really does return a “function”, which is useful in a sense, but returning an object for null (supposedly a legacy issue) is just as good as it gets.

I think the way to learn more about variables is to understand the underlying workings of variables. The original value is placed directly in the stack, and the reference value is placed in the heap (which is where it is actually stored). (If it is a constant, it is placed in the pool and seems to be part of the stack area). Normally, variable values are fetched directly from the stack, but reference values are stored in the heap.

Access to a reference type value:

  1. A variable of a reference type holds a pointer in the memory stack
  2. This pointer is used to refer to the memory address of a storage area in the memory heap
  3. When accessing a type value
  4. The pointer is used to find the storage area in the memory heap and fetch the value from it.

Such as:

  var first  = {
      name:'hahei... '
  }
  var gggiii=111222;
Copy the code

The mapping diagram is as follows:

Note: I use ref.first to refer to a reference to a store, because although we are holding a pointer, the value is parsed twice (that is, the pointer is used to find the store), rather than returning the specific data of the pointer directly. See C++ references for details.

Learn the lexical environment for the first time

I’m sure you already know what scope is, but I must mention it again. A scope is the accessible scope of an identifier, and almost any operation in Javascript involves a scope. Javascript uses lexical contexts to determine scope, which I’ll cover briefly below. (Note that I’m not using the term variable here, because when parsing an identifier range, you probably haven’t actually generated the code yet, so you can take a look at AST syntax trees if you’re interested.)

Look at the following code:

 var val=111;
 function hahaha(){
     console.log(val);
 }
 function hihihi(){
    hahaha();
 }
 hihihi();  / / / 111
Copy the code

That’s the correct output, 111.

But I prefer to put val in a function, as in:

   function hahaha(){
       console.log(val);      / / / (* *)
   }
   function hihihi(){
      var val=111;            / / / (*)
      hahaha();
   }
   hihihi();
Copy the code

Uncaught ReferenceError: val is not defined, val is not found.

Rearrange, the execution process is like this:

  1. hihihiThe function executes, and then isvalAssignment…
  2. hahahaFunction performs
  3. inhahahaCan’t findvalIdentifier, then goExternal lexical environment
  4. hahahaThe extraneous lexical environment isThe outer part of the code when the hahaha function is declared, i.e.,Global code(Global lexical environment)
  5. inGlobal lexical environmentDid not findvalAnd at the end. (please note3-5Step, findvalLooking for theFunction declares the outside of the codeRather thanFunction callThe location of.

It is time to mention the concept of Lexical Environment, which is the scope determined by code structure, also known as Lexical Scoping, as a static scope. The scope of all identifiers is determined, so to speak, when the source code is written. Of course there is dynamic scope, you can try bash scripts, it is dynamic. Hey hey. You can also refer to static scope and lexical scope for details.

It’s pretty easy to pick up the difference here, so I’m going to skip it.

Abstract lexical context

There are three common lexical environments in Javascript: block scope, global scope, and function scope.

Sometimes, we will abstract a lexical environment (scope, I will formally use lexical environment instead of scope) into pseudocode as follows:

	LexicalEnvironment = {
		OuterEnv: < ... > ,
		This :   < ... > ,
		EnvironmentRecord:{
			// ... identifiername:variable
		}
	}
Copy the code

Is simple:

  • OuterEnv: Indicates the external lexical environment of the current lexical environment
  • This: of the current lexical environmentthisThe value of, but it isThe runtimeA decision.
  • EnvironmentRecord: a mapping of identifiers to variables, but more specifically the binding of identifiers and variables (similar to references); But the concept is not important, just look at the examples. The identifiers are simply strings, and the variables refer to the data in the store. And the identifier must be for the current lexical environment, not the current code.

Such as:

  function first(){
      var a  =100;
      let d = 220;
      {     // Block, 
          var b = a+100;
          let c = b*10;
          console.log(a,b,c,d);
      }
  }
  first();  // 100 200 2000 220
Copy the code

It is important not to ignore the block-level scope in the first function.

The block level scope inside the function is:

BlockEnv = {OuterEnv: < FuncFirstEnv >, This :< window >, EnvironmentRecord:{c:< 2000 >Copy the code

Function scope:

	FuncEnv = {
		OuterEnv: < GlobalEnv > ,
		This :   < window > ,
		EnvRec:{
			a:< 100 >,
			d:< 220 >,
			b:< 200 >
		}
	}
Copy the code

OKay, I’ll stop here.

Some questions:

  1. Why useLexical environmentInstead ofscope?
    • In my opinion, lexical environment covers scope and is more specific.
    • However, lexical scope chains are also stored in[[Scope]]Attribute.
  2. What is the environmental record?
    • Records identifiers and variable bindings in the current lexical environment.
    • But identifiers are just strings of “legal identifiers.”
    • A variable refers to the contents of a storage area, but is actually a storage area.
  3. What is binding?
    • It’s hard to explain in a few words.
    • int a = 100; int& b=a;I think it’s very similar to binding.
    • A is an alias for b, the same variable with a different name.
    • The binding precondition is that the bound variable must be initialized, and instantiation alone is not enough, which is why I venture to speculate…
  4. Do you need pseudocode?
    • It’s personal, but I think it’s better in writing.

The last

When I reorganized my notes and posted them on my blog, I realized — my notes are much cleaner. Fuck.

This kind of core depth is useful and gives you a lot more flexibility when writing code. I think that’s where it’s most useful. Next article I’ll focus on for EnvironmentRecord, such as promoting ObjectEnvironmentRecord ah, DeclarativeEnvironmentRecord such as variables, temporary dead zone of what, But the Reference Specification Type is really hard to understand, if there are big guys, please clarify the confusion.

Finally: Personal understanding, often mistakes; Look carefully I do not know where, hope you do know.

Address of original note (also written by me, original note) :

Intensive reading Javascript series (I) variables, the beginning of the lexical environment; (ah… CSDN Markdown is very useful.