Home  >  Article  >  Web Front-end  >  Detailed analysis of let and const in es6 block-level binding

Detailed analysis of let and const in es6 block-level binding

不言
不言forward
2019-03-30 09:43:182450browse

This article brings you a detailed analysis of let and const in es6 block-level binding. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

Variable declaration has always been the most subtle part of js work. Unlike C language, variables are always declared when they are created. js language allows you to declare variables when you need to declare them. .

var let const variable declaration

var declaration and variable promotion.

When we use the var keyword to declare a variable, no matter where the variable is declared, it will be declared at the top of the function (if it is not within the function, it will be regarded as global) The top of the domain) This is called variable hoisting (hoisting)

var is hoisted as follows:

function getValue(condition) {
if (condition) {
var value = "blue";
// 其他代码
return value;
} else {
// value 在此处可访问,值为 undefined
return null;
}
// value 在此处可访问,值为 undefined
}

Block-level declaration let

Block-level declaration is to let the declared variable Cannot be accessed outside the specified scope. Block-level scopes are created when

  1. Inside a function,
  2. In a code block (delimited by a pair of curly braces Package)

The syntax of the let declaration is consistent with the var declaration. Since the let declaration will not promote the variable to the top of the function, we need to manually place the let declaration to the top so that the variable can be placed at the top of the entire code. Available inside the block.

As shown below:

function getValue(condition) {
if (condition) {
let value = "blue";
// 其他代码
return value;
} else {
// value 在此处不可用
return null;
}
// value 在此处不可用
}

Duplication of identifiers is prohibited

If an identifier has been defined within the code, repeated let statements will report an error

var a = 30;
//报错
let a = 30;

The a variable is declared twice: once using var and once using let. Because let cannot re-declare an existing identifier in the same scope, the let declaration here will throw an error. On the other hand, using let to declare a new variable with the same name in a nested scope will not throw an error. The following code demonstrates this:

var count = 30;
// 不会抛出错误
if (condition) {
let count = 40;
// 其他代码
}

No error will be thrown in this code, The key point is that if let is declared repeatedly in the same level code block, an error will be reported.

const constant declaration

can be declared using const syntax in es6. Variables declared using const are considered constants, meaning that their values ​​cannot be changed after being set. Because of this, all const variables need to be initialized when declared. The

// 有效的常量
const maxItems = 30;
// 语法错误:未进行初始化
const name;

maxItems variable is initialized, so its const declaration can work normally. The name variable was not initialized, causing an error to be thrown when trying to run this code. The const declaration will prevent variable binding and modification of self-generated values, which means that the const declaration will not prevent modification of variable members. For example:

const person = {
name: "Nicholas"
};
// 工作正常
person.name = "Greg";
// 抛出错误
person = {
name: "Greg"
};

Comparison of const declaration and let declaration

  1. First of all, they are block-level declarations, which means that constants cannot be outside the statement block in which they are declared. is accessed, and the declaration will not be promoted. Examples are as follows:

if (condition) {
const maxItems = 5;
// 其他代码
}
// maxItems 在此处无法访问
  1. They will cause an error to be thrown when they are declared repeatedly in the unified scope

Temporary dead zone

When we use let or const to declare, we cannot access it before reaching the declaration point. If we try to access it, it will cause a Citation error. This problem occurs because of the temporary dead zone

When the JS engine looks at the next block of code and finds a variable declaration, it will promote the declaration to the function or global scope in the face of var top, while facing let or const will place the declaration in a temporary dead zone. Any attempt to access a variable within the temporary dead zone will result in a "runtime" error. Only when the variable's declaration statement is executed, the variable will be removed from the temporary dead zone and can be safely used.

Block-level binding in the loop

for (var i = 0; i < 10; i++) {
process(items[i]);
}
// i 在此处仍然可被访问
console.log(i); // 10

The output result is not the expected value but 10; it is because of the promotion of the variable caused by the var declaration. If you are smart, you will definitely think of using block-level binding to declare variables

for (let i = 0; i < 10; i++) {
process(items[i]);
}

console.log(i);

i Will the output be normal here? In fact, it will not. In this example, an error will be reported. Why? Because i is not accessible here. The variable i in this example is only available inside the for loop and is not accessible anywhere once the loop ends.

Let’s take a look at the code

var funcs = [];
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i); });
}
funcs.forEach(function(func) {
func(); // 输出数值 "10" 十次
});

You might have expected this code to output a value from 0 to 9, but instead it outputs the value 10 ten times on the same line. This is because the variable i is shared in each iteration of the loop, meaning that the functions created within the loop all have a reference to the same variable. After the loop ends, the value of variable i will be 10, so when console.log(i) is called, 10 will be printed out every time.

To fix this problem, developers use Immediately Invoked Function Expressions (IIFEs) within loops to force the creation of a new copy of the variable on each iteration, as shown in the following example:

var funcs = [];
for (var i = 0; i < 10; i++) {
funcs.push((function(value) {
return function() {
console.log(value);
}
}(i)));
}
funcs.forEach(function(func) {
func(); // 从 0 到 9 依次输出
});
let declaration inside a loop

The let declaration simplifies the loop by effectively mimicking the effect of the IIFE in the above example. On each iteration, a new

variable of the same name is created and initialized. This means you can omit the IIFE entirely and get the expected results, like this

var funcs = [];
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs.forEach(function(func) {
func(); // 从 0 到 9 依次输出
})

我们是否会想到这个问题:为什么同样的代码使用let声明会导致不一样的结果呢?
在循环中let声明每次都创建了一个新的i变量,因此在循环内部创建的函数获得了各自的i副本,而每个i副本的值都会在每次的循环迭代声明变量的时候确定了

var funcs = [],
object = {
a: true,
b: true,
c: true
};
for (let key in object) {
funcs.push(function() {
console.log(key);
});
}
funcs.forEach(function(func) {
func(); // 依次输出 "a"、 "b"、 "c"
});

本例中的 for-in 循环体现出了与 for 循环相同的行为。每次循环,一个新的 key 变量绑定就被创建,因此每个函数都能够拥有它自身的 key 变量副本,结果每个函数都输出了一个不同的值。而如果使用 var 来声明 key ,则所有函数都只会输出 "c" 。
let 声明在循环内部的行为是在规范中特别定义的,而与不提升变量声明的特征没有必然联系。事实上,在早期 let 的实现中并没有这种行为,它是后来才添加的。

循环内的常量声明

虽然es6没有明确的规范我们不能在for循环中使用const声明,然而它会根据循环方式的不同而有不同的行为,我们可以在初始化时使用const,但是当循环试图改变变量的值的时候会抛出错误,例如:

var funcs = [];
// 在一次迭代后抛出错误
for (const i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i);
});
}

在此代码中, i 被声明为一个常量。循环的第一次迭代成功执行,此时 i 的值为 0 。在
i++ 执行时,一个错误会被抛出,因为该语句试图更改常量的值。因此,在循环中你只能使
用 const 来声明一个不会被更改的变量
而另一方面, const 变量在 for-in 或 for-of 循环中使用时,与 let 变量效果相同。因
此下面代码不会导致出错:

var funcs = [],
object = {
a: true,
b: true,
c: true
};
// 不会导致错误
for (const key in object) {
funcs.push(function() {
console.log(key);
});
}
funcs.forEach(function(func) {
func(); // 依次输出 "a"、 "b"、 "c"
});

这段代码与“循环内的 let 声明”小节的第二个例子几乎完全一样,唯一的区别是 key 的值在
循环内不能被更改。 const 能够在 for-in 与 for-of 循环内工作,是因为循环为每次迭
代创建了一个新的变量绑定,而不是试图去修改已绑定的变量的值(就像使用了 for 而不是
for-in 的上个例子那样)。

全局块级绑定

let 与 const 不同于 var 的另一个方面是在全局作用域上的表现。当在全局作用域上使用 var 时,它会创建一个新的全局变量,并成为全局对象(在浏览器中是 window )的一
个属性。

总结

let和const块级作用域的引入,能够使我们减少很多无心的错误,它们的一个副作用,是不能在变量声明位置之前访问它们

块级绑定当前的最佳实践就是:在默认情况下使用 const ,而只在你知道变量值需要被更改的情况下才使用 let 。这在代码中能确保基本层次的不可变性,有助于防止某些类型的错误。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

The above is the detailed content of Detailed analysis of let and const in es6 block-level binding. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete