Previous remarks
In the past, javascript lacked block level Scope , when var is declared Declaration Promotion,Attribute variable Behaviors such as these are confusing.The new syntax for ES6 can help us better control the scope.This article details the new block-level scope binding mechanism, let and const declaration mechanism, and best practices introduced by ES6
var declaration
[Variable promotion]
Variable promotion occurs when var declarations, that is, variables can be used before they are declared with a value of undefined
function getValue(condition){ if(condition){ var value = 'blue'; return value; }else{
//The variable value, undefined, is accessible here return null; }
//The variable value, undefined, is accessible here }
Without experience with javascript development, you might think that variable value will only be created if condition is true
In practice, however, during the precompilation phase, the javascript engine will modify the above function to look like this
function getValue(condition){ var value; if(condition){ value = 'blue'; return value; }else{ return null; } }
The declaration of the variable value is promoted to the top of the function, while the initialization remains in place.If you don't pay attention, you are likely to get an error.For this reason, ES6 introduces a block-level scope to enhance control over the life cycle of variables
[Block level declaration]
Block-level declarations are used to declare variables that are inaccessible outside the scope of a specified block and that exist
1. Inside Function
Within block area between 2, {}
let declaration
The let declaration is used the same as the var declaration.Declaring variables with let instead of var limits their scope to the current block of code
function getValue(condition){ if(condition){ let value = 'blue'; return value; }else{ //variable value Does not exist here return null; } //variable value Does not exist here }
After the variable value is declared by the keyword let, it is no longer promoted to the top of the function.When the execution stream leaves the if block, the value is immediately destroyed.If the condition value is false, the value will never be declared and initialized
[No redeclaration]
Assuming that an identifier already exists in the scope, declaring it with the let keyword will throw an error
var count = 30; //Throw a grammar error //Uncaught SyntaxError: Identifier 'count' has already been declared let count = 40;
const declaration
Const is used to declare constants whose values cannot be changed once they are set.Therefore, each constant declared through const must be initialized
const num = 30; //Throw a grammar error //Uncaught SyntaxError: Missing initializer in const declaration const name;
const and let declare the teacher block level identifier, so constants are only valid in the current block of code and are destroyed as soon as they are executed outside the block.Constants are also not promoted to the top of the scope
if(condition){ const num = 30; } //Not accessible here num
[No redeclaration]
Similar to lets, declaring an existing identifier with const within the same scope can also result in syntax errors, whether the identifier is declared with var or let
var message = 'hello'; let num = 10; //Both statements throw errors const message = "goobye"; const num = 30;
[No more assignments]
The biggest difference between const and let declarations is that const declarations can no longer be assigned constants
let num1 = 10; num1= 20; const num2 = 10; //Uncaught TypeError: Assignment to constant variable. num2 = 20;
[Object properties can be modified]
The const declaration does not allow modification of bindings, but allows modification of values.This also means that once an object is declared with a const, its property values can be modified
const person = { name: 'huochai' }; //You can modify the value of an object property person.name = 'match'; //Object {name: "match"} console.log(person); //Throw a grammar error //Uncaught TypeError: Assignment to constant variable. person = { name: 'match' }
Temporary Dead Zone
Unlike var, variables declared by let and const are not promoted to the top of the scope, and accessing them before declaration can cause errors.The area from the top of the scope to the area before the variable statement is called the temporal dead zone, or TDZ for short.
if(true){ //undefined console.log(typeof value); var value = "blue"; } if(true){ //Uncaught ReferenceError: value is not defined console.log(typeof value); let value = "blue"; }
However, using this variable outside the scope of a let or const declaration will not cause errors
//undefined console.log(typeof value); if(true){ let value = "blue"; }
Circular Binding
[var statement]
The var declaration has long made it difficult to create functions in a loop because variables are still accessible outside the loop
var funcs = []; for(var i = 0; i < 10; i++){ funcs.push(function(){ //Output 10 times 10 console.log(i); }); } funcs.forEach(function(func){ func(); })
In the code above, the expected result is the output number 0-9, but it outputs 10 times in a series, because each iteration in the loop shares the variable i, the functions created inside the loop keep all references to the same variable, and the variable I at the end of the loop has a value of 10, so each time console.log(i) is called, it outputs 10
[IIFE]
To solve this problem, an immediate call function expression (IIFE) can be used in a loop to force a copy of the counter variable to be generated
var funcs = []; for(var i = 0; i < 10; i++){ funcs.push((function(value){ return function(){ //0 //1 //... //9 console.log(value); } })(i)); } funcs.forEach(function(func){ func(); })
Within the loop, the IIFE expression creates a copy of each accepted variable i and stores it as the variable value, which is the value used by the function created by the corresponding iteration, so each function invoked will get the expected value as from the 0-9 loop
[let]
The let declaration mimics what IIFE did in the example above to simplify the cycle.Each iteration cycle creates a new variable and initializes it with the value of the same variable in the previous iteration
var funcs = []; for(let i = 0; i < 10; i++){ funcs.push(function(){ //0 //1 //... //9 console.log(i); }); } funcs.forEach(function(func){ func(); })
This loop is more concise than the one above, where each time a let declaration creates a new variable I and initializes it to the current value of i, so each function created inside the loop gets a copy of its own I property
The same is true for for-in loops and for-of loops
var funcs = []; obj = { a:true, b:true, c:true } for(let key in obj){ funcs.push(function(){ //a //b //c console.log(key); }) } funcs.forEach(function(func){ func(); })
[const]
For const declarations, the normal for loop cannot be used because it cannot change the value of a variable
var funcs = []; for(const i = 0; i < 10; i++){ funcs.push(function(){ //Uncaught TypeError: Assignment to constant variable. console.log(i); }); } funcs.forEach(function(func){ func(); })
const can be used in for-in loops because each iteration in the for-in loop does not modify existing bindings but creates a new one
var funcs = []; obj = { a:true, b:true, c:true } for(const key in obj){ funcs.push(function(){ //a //b //c console.log(key); }) } funcs.forEach(function(func){ func(); })
Attribute variable
Variables declared by var automatically become properties of window objects if they are in global scope.This means that var is likely to inadvertently overwrite an existing global variable
//function RegExp() { [native code] } console.log(RegExp); var RegExp = "hello"; console.log(RegExp);//'hello' console.log(window.RegExp);//'hello'
Variables declared with let or const do not become properties of window objects
let RegExp = "hello"; console.log(RegExp);//'hello' console.log(window.RegExp);//function RegExp() { [native code] }
Therefore, if you want to define variables under a window object, use the var declaration.If you don't want it, make let or const
Best Practices
const is used by default, let is used only if you really need to change the value of a variable
Since the values of most variables should not change after initialization, unexpected changes in variable values are the source of many bug s