[In-depth understanding of ES6] block-level scope binding

1. var declaration and variable promotion mechanism

Hoisting mechanism: Variables declared with the keyword var will be treated as variables living at the top of the current scope.

function getValue(condition){
	if(condition){
		var value = "blue";
		console.log(value);
	}else{
		// 此处可访问变量value,其值为undefined
		return null
	}
	// 此处可访问变量value,其值为undefined
}

The JavaScript engine will modify the above getValue function to the following. The declaration of the variable value is hoisted to the top of the function, and the initialization operation remains in place. To this end, ES6 introduces block-level scope to strengthen the control over the variable declaration cycle.

function getValue(condition){
	var value;
	if(condition){
		value = "blue";
		console.log(value);
	}else{
		return null
	}
}

 

2. Block-level declarations

Block-level declarations are used to declare variables that cannot be accessed outside the scope of the specified block.

Block-level scope exists in:

  • inside the function
  • block (the area between '{}').

2.1. let statement

  • The usage is the same as var, but the declaration will not be hoisted;
  • Redeclaration within the same scope is prohibited;
  • If the current scope nests another scope, you can use let to declare a variable with the same name in the nested scope.
function getValue(condition){
	if(condition){
		var value = "blue";
		console.log(value);
	}else{
		// 变量value在此处不存在
		return null
	}
	// 变量value在此处不存在
}
/**禁止重声明*/

var count = 30;
// 抛出语法错误
let count = 40;

if(condition){
	// 不会抛出错误
	let count = 40;
}

2.2. const declaration

  • The declaration is a constant and must be initialized;
  • Redeclaration within the same scope is prohibited;
  • Cannot be reassigned (constant object can modify the value;
  • When const declares an object, the binding is not allowed to be modified, but the value can be modified.
// 有效的常量
const maxItems = 30;
// 语法错误,未初始化
const name;


if(condition){
	const cnt = 40;
}
// 在此处无法访问cnt


let age = 20;
// 抛出错误,重声明
const age = 15;



const pos = 30;
// 抛出语法错误,不能重新赋值
pos = 35;



const person = {
	name: 'Nicholas'
};
// 可以直接修改对象属性的值
person.name = 'Fleur';
// 直接给person赋值,即要改变person的绑定,会抛出语法错误。
person = {
	name: 'DpprZ'
}

 

3. Temporal Dead Zone (Tempprral Dead Zone, TDZ) 

Since the console.log(typeof value) statement would throw an error, the statement defining and initializing the variable value with let will not execute. The value at this point is still in what the JavaScript community calls a "temporary dead zone". TDZ is often used to describe the non-promoting effect of let and const.

if(condition){
	console.log(typeof value);  // 引用错误
	let value = 40;
}
console.log(typeof value);  // "undefined"
if(condition){
	let value = 40;
}

 When the JS engine scans the code and finds variable declarations:

  • var declarations: Hoist them to the top of the scope.
  • let and const declarations: place declarations in the TDZ. Accessing variables in the TDZ triggers a runtime error. Only after the variable declaration statement is executed, the variable will be removed from the TDZ, and then it can be accessed normally.

 

4. Block-scoped bindings in loops

In the for loop, the counter variable is limited to the inside of the loop by let.

for(var i = 0; i < 10; i++){
	// 更多代码
}
// 在这里仍然可以访问变量i
console.log(i); // 10

for(let i = 0; i < 10; i++){
	// 更多代码
}
// i在这里不可访问,抛出错误
console.log(i); 

 

5. Functions, let declarations, and const declarations in loops

let funcs = [];
for(var i = 0; i < 10; i++){
    funcs.push(function(){
        console.log(i)
    })
}
/*
每个funcs[]中都存在一个函数:
	ƒ (){ console.log(i) }
*/
funcs.forEach(function(func){
    func(); // 10个10
})

Because each iteration of the loop here also shares the variable i, the functions created inside the loop all retain references to the same variable.
Two solutions to this problem:

Use an immediately invoked function expression (IIFE) in a loop to force a copy of the counter variable.

let funcs = [];

for(var i = 0; i < 10; i++){
    funcs.push(function(value){
        return function(){
        	console.log(value)
        }
    })
}

funcs.forEach(function(func){
    func(); // 0 1 2 3......9
})

Declaring a counter with let: Each iteration of the loop creates a new variable i and initializes it with the value of the variable of the same name from the previous iteration. So each function created inside the loop can get its own value of i. It is crucial to understand that the behavior of let declarations inside loops is specifically defined in the standard, it does not necessarily relate to the non-hoisting nature of let!

let funcs = [];

for(let i = 0; i < 10; i++){
    funcs.push(function(){
        console.log(i)
    })
}

funcs.forEach(function(func){
    func(); // 0 1 2 3...... 9
})
  •  let statement: declare counter, for-in, for-of
  • const declaration: value that does not change within the life cycle, for-in, for-of

 

6. Global block scope bindings

Differences in the behavior of var, let, and const in the global scope:

var creates a new variable as the global object (the window object in the browser environment), inadvertently overwriting existing global properties.

let, const will create a new binding under the global scope, but the binding will not be added as a property of the global object. In other words, what cannot be covered is only shadowed. 

Guess you like

Origin blog.csdn.net/m0_62811051/article/details/132183042