Variable declarations

Variables in ECMAScript are loosely typed, meaning that variables can hold any type of data. Each variable is just a named placeholder to hold the value.

In strict mode, you cannot define variables named eval and arguments.

var

You can store any type of value.

ECMAScript implements variable initialization, so you can define a variable and set its value at the same time.

var message = "hi";
Copy the code

Once defined, you can change not only the value, but also the type. This is legal, but not recommended and rarely seen by programmers.

var message = "hi";
message = 100;
Copy the code

Uninitialized, the variable holds a special value called undefined.

Multiple variables can be declared at once:

Because ECMAScript is loosely typed, it is possible to initialize with a single statement using different data types.

var message = "hi",
  found = "false",
  age = 29;
Copy the code

Var can be repeated:

var age = 16;
var age = 26;
var age = 36;
Copy the code

Var declares scope

A variable declared using var becomes a local variable of the function that contains it. For example, inside a function, var a variable that will be destroyed when the function exits.

function test() {
  var message = "hi";
}
test();
console.log(message);
Copy the code

Because Message is destroyed after the function call, the above code will report an error when it tries to print. You can omit var and declare it as a global variable.

function test() {
  message = "hi";
}
test();
console.log(message);
Copy the code

Use this method with caution. In strict mode, a referenceError is thrown. And it can be confusing whether it was intentional or a mistake.

Var variable declaration hoist

console.log(age);
var age = 26;
function test() {
  console.log(age);
  var age = 30;
}
Copy the code

Code like this is error-free; it’s not that the parser is out of order. Instead, the VAR declaration gets pushed up to the top and becomes

var age;
console.log(age);
age = 26;
function test() {
  var age;
  console.log(age);
  var age = 30;
}
Copy the code

let

Let declares block scope, while var declares function scope. This is the most obvious difference between them.

if (true) {
  var name = "Matt";
  console.log(name); // Matt
}
console.log(name); // Matt
Copy the code
if (true) {
  let name = "Matt";
  console.log(name); // Matt
}
console.log(name); // undefined
Copy the code

Variables declared with let can only be used within the if block. It has a smaller scope than VAR, so it naturally cannot be used outside functions.

Let does not allow repeated declarations, a feature known as declaration masking:

let age;
let age;
Copy the code

SyntaxError is reported, and the identifier is already declared.

And because the scope of the LET declaration is within the block, it is legal to use the same identifier in the following nesting.

let age = 30;
if (true) {
  let age = 26;
}
Copy the code

Let has no variable declaration promotion, only a temporary dead zone

The moment of execution prior to the LET declaration is called a temporal dead zone and a ReferenceError is thrown.

Variables declared globally by the let do not become properties of the Window object

This is different from var:

var name = "Matt";
console.log(window.name); // Matt

let age = 26;
console.log(window.age); // undefined
Copy the code

Let cannot be declared with conditions

if (typeof name === "undefined") {
  let name;
}
Copy the code

Conditionally declared let variables like this can still only be used within a block, and global let variables cannot be conditionally declared.

Not being able to use conditional declarations is actually a good thing, because conditional declarations are an anti-pattern. It makes programs harder to understand and maintain. There could have been a better way to replace it.

Let in the for loop

An iterated variable declared with var penetrates the body of the loop:

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

This problem is not present with lets:

for (let i = 0; i < 5; i++) {
  // loop logic
}
console.log(i); ReferenceError: I is not defined
Copy the code

There is another problem with var, which is often asked to your face:

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

Expected output: 0, 1, 2, 3, 4

The actual output is: 5, 5, 5, 5, 5

The reason for this is that setTimeout is a timeout logic that will start execution after the loop exits, and when the loop exits, the iteration variable holds the value that causes the loop to exit: 5. All I’s are the same variable, so the output is the same final value. One solution to this is to use an immediate function expression (IIFE) to capture the value of I at each iteration.

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

Or declare iterated variables using let. JavaScript then declares a new iteration variable behind the scenes for each iteration loop. So it has five I’s, 0, 1, 2, 3, 4, and each setTimeout refers to a different instance of a variable.

for (let i = 0; i < 5; i++) {
  setTimeout(() = > console.log(i), 0);
}
Copy the code

This behavior of declaring one instance of an independent variable per iteration applies to all styles of for loops, including for-in and for-of.

const

Const is basically the same as let, with the only important difference that it must simultaneously initialize the variable and cannot change its declared value.

Const also does not allow repeated declarations.

The scope of const declarations is also a block.

But const only limits the variables it points to. That is, if const declares an object, it is legal to modify properties within the object.

Const is generally not used to declare an iteration variable because it cannot be modified. But it does make sense in for-in and for-of:

for (const i = 0; i < 5; i++) {} // TypeError: Assigns values to constants

let i = 0;
for (const j = 0; i < 5; i++) {
  console.log(j);
}
// 0 0 0 0 0

for (const key in { a: 1.b: 2{})console.log(key);
}
// a b

for (const value of [1.2.3.4.5]) {
  console.log(value);
}
// 1, 2, 3, 4, 5
Copy the code