You can define your variables in JavaScript using two keywords - the let keyword and the var keyword. The var keyword is the oldest way of defining and declaring variables in JavaScript whereas the let is fairly new and was introduced by ES15.
您可以使用两个关键字( let关键字和var关键字) 在JavaScript中定义变量 。 var关键字是在JavaScript中定义和声明变量的最古老的方法,而let是相当新的,是ES15引入的。
In this article, we'll look at the differences between the two so you know when to use which for your variables.
在本文中,我们将研究两者之间的区别,以便您知道何时将哪个变量用于变量。
Open the chrome dev console to try out the examples by right-clicking on the browser → selecting inspect → selecting console or simply type f12.
通过右键单击浏览器→选择检查→选择控制台,打开chrome dev控制台以尝试示例,或者直接键入f12。
Example 1:
范例1:
var size=32;
console.log(size);
Output
输出量
32
Example 2:
范例2:
var size=63;
console.log(size);
Output
输出量
63
We declared a variable size with a value 32. Then we redeclared it with another value, 63. Everything looks fine till now.
我们声明了一个可变大小,值为32 。 然后,我们用另一个值63对其进行了重新声明。 到目前为止一切都很好。
let length=14;
console.log(length);
Output
输出量
14
let length=14;
let length=20; //will produce error
console.log(length);
Output
输出量
Uncaught SyntaxError: Identifier 'length' has already been declared
at <anonymous>:1:1
let length=14;
length=20; //no produce error
console.log(length);
Output
输出量
20
Now we create a length variable with a value 14 but this time using the let keyword. When we redeclare the same variable with another value we get a SyntaxError saying it has already been declared. The first point of difference between let and var is that using var we can redeclare those variables but with let, we can only redefine them, not redeclare them. When we reassign the value 20 to the variable length, we get no error on the console and our length variable happily takes a new value.
现在我们创建一个长度变量,值为14,但是这次使用let关键字 。 当我们用另一个值重新声明相同的变量时,我们得到一个SyntaxError,它已经被声明。 let和var之间的第一点区别是,使用var可以重新声明这些变量,但是使用let ,我们只能重新定义它们,而不能重新声明它们。 当我们将值20重新分配给变量length时 ,在控制台上没有错误,并且我们的length变量愉快地采用了一个新值。
var ironMan = 'red';
var captainAmerica = 'blue';
if (ironMan === 'red') {
var ironMan = 'silver';
let captainAmerica = 'golden';
console.log(ironMan);
console.log(captainAmerica);
}
Output
输出量
silver
Golden
var ironMan = 'red';
var captainAmerica = 'blue';
if (ironMan === 'red') {
var ironMan = 'silver';
let captainAmerica = 'golden';
console.log(ironMan);
console.log(captainAmerica);
}
Output
输出量
silver
Blue
The next difference between the two is the scope. You can observe from the above code that captainAmerica is declared again inside using the let keyword with a value 'golden' and inside that if block it persists that value, however, outside that if block when we log it's value to the console we get the older value 'blue' which was defined outside the if block. Thus variables declared using the let keyword have block scope. On the other hand, we changed the value of ironMan inside the if block and it continues to hold that value even after the if block is over. We can say that var takes the scope of it's enclosing execution context which can be a function or even the global scope as in this case.
两者之间的下一个区别是范围。 您可以从上面的代码中观察到,在captainAmerica内部再次使用let关键字声明了“黄金”值,并且在if块内部将其持久保留该值,但是在if块之外,当我们将其值记录到控制台时,我们得到了在if块外定义的旧值“ blue” 。 因此,使用let关键字声明的变量具有块范围。 另一方面,我们更改了if块内的ironMan的值, 即使 if块结束,它仍继续保持该值。 我们可以说var接受其封闭执行上下文的范围,在这种情况下,它可以是函数甚至是全局范围。
Heads up: The reason let was introduced was to avoid using global variables and namespaces everywhere. It's a bad, no wait, terrible programming habit. Avoid using global variables where their global scope renders absurd. Use let wherever possible.
注意:引入let的原因是为了避免在各处使用全局变量和名称空间。 这是一种不好的,迫不及待的可怕的编程习惯。 避免在全局变量变得荒谬的地方使用全局变量。 尽可能使用let 。
Finally, the last difference I want to talk about is Hoisting. Consider the following piece of code,
最后,我要谈的最后一个区别是吊装 。 考虑下面的代码,
x = 5;
console.log(x);
var x;
Output
输出量
5
If you've worked with languages like C/C++ you might find it strange. In such languages, you can expect an error saying something like x is not defined because compiler reads from top to bottom. So is JS also executed from top to bottom? Well, if it were, you wouldn't be able to do this. Then how come we can use a variable and declare it later? The answer is hoisting. Hoisting means moving all declarations to the top. This means that while executing the code, all variable declarations are on the top so till the time you come to x=5 line you already know that x has been declared a variable somewhere in the program.
如果您使用过C / C ++之类的语言,则可能会觉得很奇怪。 在这样的语言中,您可能会遇到一个错误,即未定义类似x的内容,因为编译器从上到下读取。 JS也是从头到尾执行吗? 好吧,如果是这样,您将无法做到这一点。 那么我们如何使用变量并在以后声明它呢? 答案正在提升。 吊装意味着将所有声明移到顶部。 这意味着在执行代码时,所有变量声明都位于顶部,因此直到您到达x = 5行时,您已经知道x已在程序中的某个位置声明为变量。
y = 3;
function setRandom(y) {
console.log('Before declaring y: ', y);
}
setRandom();
var y;
console.log('After declaring y: ', y);
Output
输出量
Before declaring y: undefined
After declaring y: 3
Let's try to hoist a variable using let,
让我们尝试使用let提升变量,
x = 5;
console.log(x);
let x;
Output
输出量
VM2466:1 Uncaught ReferenceError: Cannot access 'x' before initialization
at <anonymous>:1:2
We get an error saying we can't access it before it is even initialized. So are variables declared with the let keyword not hoisted? They are, but they're hoisted in a temporal dead zone. A zone where you can use variables that have not been defined yet.
我们收到一条错误消息,说我们甚至无法在初始化之前访问它。 那么,没有悬挂用let关键字声明的变量吗? 它们是,但是它们被吊在一个临时的死区中。 您可以在其中使用尚未定义的变量的区域。
Note: if you are using strict mode in your JavaScript then you're more likely to run into getting undefined values for such types of code because strict mode does not allow any hoisting to take place.
注意:如果您在JavaScript中使用严格模式,那么您很可能会遇到此类代码的未定义值,因为严格模式不允许任何提升。
So is hoisting in TDZ useless? Well not really, consider the following example using an asynchronous function.
那么在TDZ中吊起是没有用的吗? 并非如此,请考虑以下使用异步函数的示例。
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000)
}
Output
输出量
3
Out setTimeout is an asynchronous function and after 1 sec it prints the value of i which was incremented 4 times while that asynchronous function was running. However if we use let instead of var,
setTimeout输出是一个异步函数,在1秒钟后它将打印i的值,该值在该异步函数运行时增加了4倍。 但是,如果我们使用let而不是var ,
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000)
}
Output
输出量
0
1
2
Now we get all the values that i took during that loop traversal. This is because of the TDZ or the temporal dead zone where let is hoisted. Thus using async can help you retain your values through TDZ hoisting if you use let instead of var. Remember to clean your code by replacing all var with let and make it a good practice to use block scopes instead of global scopes!
现在,我们所有的值, 我该循环遍历期间举行。 这是因为TDZ或悬挂了let 的时间盲区 。 因此,如果使用let而不是var,则使用async可以帮助您通过TDZ提升保留值。 请记住通过用let替换所有var来清理代码,并使其成为使用块范围而不是全局范围的好习惯!
翻译自: https://www.includehelp.com/code-snippets/var-vs-let-in-javascript.aspx