Variables

A variable "stores" a value for future uses. We refer them by their names. We can "assign" them a new value if we want to.

You can use console.log(...) to print/show the current value of a variable. Using alert(...) can work too, but that's going to be a bit intrusive.

In the examples below, we will only assign numbers as values. But there are other kinds of values as you shall see later.

Declaring variables

You can declare a variable with let, const, or var. Declaring a variable with const turns it into a constant that cannot be re-assigned.

let

A variable declared with let can be re-assigned:

let a = 100;
let b = 101;
console.log(a, b); //=> 100 101

a = 200;
b = 201;
console.log(a, b); //=> 200 201

const

A variable declared with const cannot be re-assigned (it's a constant):

const PI = 3.14159265359;
console.log(PI); //=> 3.14159265359

// A constant cannot be re-assigned
// The statement below will throw an error
PI = 123456;

var

This was the only way to declare a variable prior to ES6. This behaves somewhat like let, but because of its "quirky" hoisting behavior, you shouldn't use this.

// You can actually declare multiple variables in one line using ','
var a = 1, b = 2, c = 3;
console.log(a, b, c); //=> 1 2 3
c = -1;
console.log(a, b, c); //=> 1 2 -1

Scope of variables

Scope of let and const

They are block-scoped. Loosely speaking, their scope is between the nearest { and }. (For for loops, the scope includes the loop condition and loop body.)

You cannot redeclare the same variable name twice in the same scope with let or const (doing so will throw an error).

However, you can declare the same variable name in a nested scope:

const A = 1;

if (A === 1) {
  const A = 2;
  console.log(A); //=> 2
}

console.log(A); //=> 1

Scope of var

They are function-scoped. Their scope is the current function, no matter how deep they are declared in the function. (They are "hoisted" to the top of the enclosing function.)

Unlike let and const, you can redeclare the same variable name multiple times in the same scope with var:

function myFunction() {
  // This doesn't throw an error because the declaration
  // of `a` is "hoisted" to the top of the function 
  console.log(a); //=> undefined
  
  // You can redeclare with var multiple times
  var a = 1;
  var a = 2;
  console.log(a); //=> 2
}

myFunction();

Global variables

Variables that are declared in the top-level scope are global variables. They are available everywhere inside their scope.

Scope of global variables

  • In Node.js and client-side JavaScript "modules" (.mjs), the scope of a global variable is the file that it is defined in.
  • In traditional client-side JavaScript (the default <script>), the scope of a global variable is the HTML document in which it is defined.

The global object

As of ES2020, you can reliably access the global object using globalThis.

  • In Node.js, the global object refers to global (globalThis.global)
  • In browsers, the global object refers to window (globalThis.window)

The global object contains properties that you can refer to directly (as if they are global variables) like undefined, Infinity, NaN, eval(), Date(), String(), Object(), etc.

const globalObject = globalThis;
const globalPropertyNames = Object.getOwnPropertyNames(globalObject);
console.log(globalObject);
console.log(globalPropertyNames);

Global variables defined using let, const, and var

  • Global variables defined using let and const cannot be accessed from the globalThis property
  • Global variables defined using var can be accessed from the globalThis property (it's like writing globalThis.myVar = 'something')*

(*) The analogy isn't perfect, though. You cannot do something like delete globalThis.myVar.

Destructoring assignment

If you don't get what I'm talking about here, just skip this section first and come back after you learned objects and arrays.
Once you are familiar with arrays and objects, ES6 introduces the shortcut to "extract" properties of an object or elements of an array.

Object destructoring

const obj = { a: 1, b: 2, c: 3, d: 4 };
// The same as doing:
// const a = obj.a;
// const myB = obj.b;
const { a, b: myB } = obj;
console.log(a, myB); //=> 1 2

Note that you can also set the default value of the extracted variable:

const obj = { a: 1, b: 2, c: 3, d: 4 };
const { x, y = 5 } = obj;
console.log(x, y); //=> undefined 5

... or even get the rest of the unextracted variables:

const obj = { a: 1, b: 2, c: 3, d: 4 };
const { a, b, ...rest } = obj;
console.log(rest); //=> { c: 3, d: 4 }

Array destructoring

const arr = [1, 2, 3, 4, 5];
let [a, b] = arr;
console.log(a, b); //=> 1 2
[b, a] = [a, b];
console.log(a, b); //=> 2 1

Note that you can skip some indices:

const arr = [1, 2, 3, 4, 5];
let [a, , b] = arr;
console.log(a, b); //=> 1 3

... or even get the rest of the array:

const arr = [1, 2, 3, 4, 5];
let [a, b, ...rest] = arr;
console.log(rest); //=> [ 3, 4, 5 ]

References

  • JavaScript: The Definitive Guide, 7th Edition (David Flanagan)Chapter 3. Types, Values, and Variables