In this section, the target

  1. Master scope chain in JS.
  2. Master three types of scope in JS: global scope, local scope, block scope.
  3. Master the application of anonymous function execution in JS.

Content in this paper,

This paper introduces the concept of scope, JS scope chain (scope chain), derived from the scope chain of global scope, function scope concept, and finally explained the content of block scope.

Read for 30 to 40 minutes.

Scope introduction

Scopes are a common topic in a programming language. Scopes indicate where variables can and cannot be called once they have been declared, and when to destroy them.

In JS scopre, we need to understand the scope chain, so that is easy.

Scope chain

We know that a function is both a type and an object, and since it’s an object, it has properties and methods. Within the function there is an attribute [[Scope] that stores accessible data objects.

When accessing a variable within a function, search within [[Scope]] until it is found.

From the inside and outside of the function structure, it is searched from the inside out, the outermost layer is the global data object.

This is called a chain.

Example 1, declare a variable I, followed by a function f.

let i = 1;
function f() {}console.log([f]); // Print the function f
Copy the code

Among them:

Here's a trick. If YOU print f, chrome will print out the function definition, and if the package is in an array you can see the function object.Copy the code

Run to view:

We can see the structure inside the [[Scope]] property, where:

Subscript 0 has an I: 1 which is the declared variable let I = 1; Subscript 1 is a global data object.Copy the code

Think about:

According to the description above, can I be accessed in function f?

Answer:

Yes, because the I variable is inside the function’s property [[Scope]].

let i = 1;
function f() {
	console.log(i); / / 1
}
f();
Copy the code

In example 2, the previous example was 2 layers, let’s look at another layer, we declare a function B in function F, and then look at b in the console.

let i = 1;
function f() {
	let j = 2;
	function b() {
		let k = 3;
		console.log(i, j, k); / / 1 2 3
	}
	console.log([b]); // Print the function b
}
f();
Copy the code

Run to view the result:

Scope classification

According to the characteristics of scope chain, combined with the habits of other languages, we can divide js scope into the following three types:

1. Global scope. 2. Function scope.Copy the code

But because the above two scopes can cause variable interference, ES6 introduces another scope:

3. Block scope.Copy the code

Each scope is described in turn.

Global scope

From the scope chain example, the variable I can be accessed in both f and B functions. This variable I is declared in the outermost layer of JS and can be used globally. This is the global scope.

Such as:

let a = 10;
console.log(a); / / 10
function f(){
	console.log(a); / / 10
	a = 11;
}
f();
console.log(a); / / 11
Copy the code

Among them:

The variable a is defined at the periphery of js, so the scope of a is global. The variable A can be accessed outside the function. Variable A can also be accessed inside function F.Copy the code

Function scope

In the scope chain example, the variable j is declared in function F and can only be accessed in f and b functions, but not in the outermost layer.

This is a variable that is defined inside a function, and its scope is inside the function, and this can be called a function scope, or a local scope.

Such as:

function f(){
	let a = 10;
	console.log(a); // access variable A in function f, print 10
	function b() {
		console.log(a); // access variable A in function b, print 10
		a = 11; // change variable A in function b
		console.log(a); // access variable A in function b, print 11
	}
	b();
}
f();
console.log(a); // Uncaught ReferenceError: a is not defined
Copy the code

Among them:

The variable a is defined inside the function, so the scope of a is inside the function. It's accessible in f. It's also accessible in the b function. If variable A is printed in the outermost layer, an undefined error is reported for variable A.Copy the code

Block scope

The above two types of scope can cause variable interference in certain business scenarios, and ES6 introduces block-level scopes to solve this problem. Here’s a three-step approach to the problem:

1. Why block scope? 2. What is the block scope? 3. Block scope application.Copy the code

1) Why block scope?

Let’s look at an example of variable interference.

var i = 10; // Global variables
for (var i = 0; i < 5; i++) {}
console.log(i); / / 5
Copy the code

Think about:

Why did the last example print I, 5?

Answer:

Because in the for loop, we declare another variable I, and we replace the global variable I, and we exit the loop with I = 5, so we print 5.

This example is relatively simple and easy to see, but in practice it is often thousands of lines of code, which is a bit scary to think about.

So ES6 introduced block-level scope to solve this problem. For downward compatibility, var cannot be modified, so the keyword let was introduced. In ES6, let declared variables are block scope.

2) What is the block scope?

Let’s see what the block is:

{
	// This is the code inside the block
}
Copy the code

This looks a bit abstract, but it is actually the {} of syntax structures, such as if, for, while, and try catch blocks.

for(... Omitted) {// This is a block
}

while(... Omitted) {// This is a block
}

try {
	// This is a block
} catch(error) {
	// This is a block
}
Copy the code

Var and let declare variables inside and outside the block.

{
	var a = 1;
	console.log(a); / / 1
}
console.log(a); / / 1
Copy the code
{
	let a = 1;
	console.log(a); / / 1
}
console.log(a); // Uncaught ReferenceError: a is not defined
Copy the code

The results show that the variables declared by the let can only be accessed inside the block, and the var can be accessed outside the block.

3) Block scope application

Improve the above variable interference example to achieve no interference with each other.

Var = let; var = let; var = let;

var i = 10; // Global variables
for (let i = 0; i < 5; i++) {}
console.log(i); / / 5
Copy the code

Because the variable I declared by let is inside the loop block, the scope is not affected outside.

Anonymous functions execute themselves

Above, let was used to solve the problem of variable interference. Before ES6, anonymous function self-execution was widely used to solve the problem.

Back to the example of variable interference:

var i = 10; // Global variables
for (var i = 0; i < 5; i++) {
	console.log(i); // Prints 0 through 4
}
console.log(i); / / 5
Copy the code

Change the way anonymous functions execute themselves:

var i = 10; // Global variables
(function() {
	for (var i = 0; i < 5; i++) {
		console.log(i); // Prints 0 through 4
	}
})()
console.log(i); / / 10
Copy the code

Anonymous function self-execution: encapsulate code in an anonymous function and execute it directly.

Anonymous functions execute themselves, isolating the scope of a variable from the outside. Common frameworks such as jquery handle this.

This section summarizes

  1. The [[Scopes]] property of a function in JS stores accessible data objects.
  2. When variables are accessed within a function, they are searched in [[Scopes]], called scope chain.
  3. According to the principle of scope chain, scope can be divided into global scope and function scope.
  4. In order to avoid variable interference, ES6 introduced block scope, which needs to be used with let.

exercises

  1. What is the difference between let and var? Say what you understand.
  2. Read the following two codes, analyze the output, and explain why.

The first paragraph:

for (var i = 0; i < 10; i++) {
	setTimeout(function(){
		console.log(i);
	}, 1000);
}
Copy the code

The second paragraph:

for (let i = 0; i < 10; i++) {
	setTimeout(function(){
		console.log(i);
	}, 1000);
}
Copy the code
  1. Read the code below, analyze the output, and explain why.
if (true) {
	let i = 0;
}
console.log(i); / / output?
Copy the code
  1. Read the code below, analyze the output, and explain why.
let i = 6;

function f() {
	let j = 10;
	b();
	c();

	function b() {
		let k = 88;
		console.log(j); / / output?
		j = 11;
	}

	function c() {
		console.log(typeof k); / / output?
		i = 7;
		console.log(j); / / output?
	}
}
f();
console.log(i); / / output?
console.log(j); / / output?
Copy the code