0%
Modern JavaScript: Variables with let and const

Variables and Types

The fundamentals of modern variables

10-15 min

Modern JavaScript: Variables, Types, and Data Structures

In this tutorial, we will explore the fundamentals of modern JavaScript: how to declare variables, understand the different data types, work with operators, and use the essential data structures.

JavaScript is a dynamic and flexible language that has evolved considerably since its creation. With the arrival of ES6 (ECMAScript 2015) and later versions, the language now offers powerful, modern features.

Declaring Variables

In modern JavaScript, there are three ways to declare variables:

let

let lets you declare variables whose scope is limited to the block in which they are defined:

let age = 25;
age = 26; // Reassignment is allowed

if (true) {
    let message = "Hello"; // Variable limited to this block
    console.log(message); // "Hello"
}
// console.log(message); // Error: message is not defined

const

const lets you declare constants whose value cannot be reassigned:

const PI = 3.14159;
// PI = 3.14; // Error: cannot reassign a constant

const personne = { nom: "Alice" };
personne.nom = "Bob"; // Allowed - the contents can change
// personne = {}; // Error: cannot reassign the reference

var (the old way)

var was the only way to declare variables before ES6. Its scope is either function-level or global:

var x = 10;
var x = 20; // Redeclaration is allowed (problematic)

if (true) {
    var y = 30; // Scope is not limited to the block
}
console.log(y); // 30 - y is accessible here

Best Practices

In modern JavaScript, prefer:

  • const by default for any variable that will not be reassigned
  • let when reassignment is necessary
  • Avoid var unless you are working with legacy code

Data Types

JavaScript is a dynamically typed language, which means you don’t need to declare the type of a variable.

Primitive Types

1. Number

JavaScript uses a single type for all numbers:

const entier = 42;
const decimal = 3.14;
const exponentiel = 2.5e5; // 250000
const binaire = 0b1010; // 10
const octal = 0o744; // 484
const hexadecimal = 0xFF; // 255

// Special values
const infini = Infinity;
const pasUnNombre = NaN; // Not a Number

// Checks
console.log(isNaN(pasUnNombre)); // true
console.log(isFinite(infini)); // false

2. String

JavaScript offers several ways to create strings:

// Single quotes
const prenom = 'Marie';

// Double quotes
const nom = "Dupont";

// Template literals (backticks) - ES6
const age = 30;
const message = `${prenom} ${nom} a ${age} ans.`;

// Useful methods
console.log(prenom.toUpperCase()); // MARIE
console.log("  texte  ".trim()); // "texte"
console.log("abc,def".split(",")); // ["abc", "def"]
console.log("Hello".includes("ell")); // true

3. Boolean

const estMajeur = true;
const estInscrit = false;

// Conditional expressions
const a = 5;
const b = 10;
console.log(a < b); // true
console.log(a === b); // false (strict equality)
console.log(a >= 5); // true

4. Undefined

undefined represents a variable that has been declared but has no assigned value:

let resultat;
console.log(resultat); // undefined

// Check
console.log(typeof resultat === 'undefined'); // true

5. Null

null represents the deliberate absence of a value:

const donnees = null;

// Watch out for the pitfall
console.log(typeof null); // "object" (historical JavaScript bug)
console.log(donnees === null); // true (use strict equality)

6. Symbol (ES6)

Symbol creates unique, immutable identifiers:

const id1 = Symbol('id');
const id2 = Symbol('id');

console.log(id1 === id2); // false - each Symbol is unique

7. BigInt (ES2020)

To represent integers of arbitrary size:

const grandNombre = 1234567890123456789012345678901234567890n;
const autreFacon = BigInt("9007199254740991");
console.log(typeof grandNombre); // "bigint"

Reference Types (Objects)

1. Object

Objects are collections of key-value pairs:

// Creating an object literal
const personne = {
    prenom: "Jean",
    nom: "Dupont",
    age: 30,
    adresse: {
        ville: "Paris",
        codePostal: "75001"
    }
};

// Accessing properties
console.log(personne.prenom); // "Jean"
console.log(personne["nom"]); // "Dupont"

// Adding/modifying properties
personne.email = "jean.dupont@example.com";
personne.age = 31;

// Object methods
const cles = Object.keys(personne); // ["prenom", "nom", "age", "adresse", "email"]
const valeurs = Object.values(personne); // ["Jean", "Dupont", 31, {...}, "jean..."]

2. Array

Arrays are ordered collections of values:

// Creating an array
const fruits = ["pomme", "banane", "cerise"];
const mixte = [1, "deux", true, null, { clé: "valeur" }];

// Accessing elements (zero-indexed)
console.log(fruits[0]); // "pomme"

// Useful methods
fruits.push("orange"); // Adds to the end
fruits.pop(); // Removes the last element
fruits.unshift("fraise"); // Adds to the beginning
fruits.shift(); // Removes the first element

// forEach loop
fruits.forEach((fruit, index) => {
    console.log(`${index}: ${fruit}`);
});

// Transformation methods (do not modify the original array)
const fruitsMajuscules = fruits.map(fruit => fruit.toUpperCase());
const fruitsCourts = fruits.filter(fruit => fruit.length < 6);
const total = [1, 2, 3, 4].reduce((acc, val) => acc + val, 0); // 10

3. Function

In JavaScript, functions are first-class objects:

// Function declaration
function saluer(nom) {
    return `Bonjour, ${nom} !`;
}

// Function expression
const direAuRevoir = function(nom) {
    return `Au revoir, ${nom} !`;
};

// Arrow function (ES6)
const multiplier = (a, b) => a * b;

// Function as a parameter
function executerFonction(fn, valeur) {
    return fn(valeur);
}
console.log(executerFonction(saluer, "Marie")); // "Bonjour, Marie !"

4. Date

const maintenant = new Date();
const dateSpecifique = new Date("2023-12-31T23:59:59");
const timestamp = dateSpecifique.getTime(); // milliseconds since January 1, 1970

5. Map and Set (ES6)

// Map - collection of key-value pairs (keys of any type)
const utilisateurs = new Map();
utilisateurs.set('u1', { nom: "Alice", age: 25 });
utilisateurs.set('u2', { nom: "Bob", age: 30 });

// Set - collection of unique values
const nombres = new Set([1, 2, 3, 3, 4, 4, 5]); // {1, 2, 3, 4, 5}

Type Checking

To check the type of a variable, use the typeof operator:

console.log(typeof "hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof { a: 1 }); // "object"
console.log(typeof [1, 2, 3]); // "object" (arrays are objects in JS)
console.log(typeof function() {}); // "function"

For arrays, use Array.isArray():

console.log(Array.isArray([1, 2, 3])); // true

Type Conversion

JavaScript often performs implicit conversions, but you can also do them explicitly:

// Conversion to string
const num = 42;
const numStr = String(num); // "42"
const autreMethode = num.toString(); // "42"

// Conversion to number
const str = "42";
const strNum = Number(str); // 42
const parseMethode = parseInt(str, 10); // 42 (base 10)
const parseFloat = parseFloat("3.14"); // 3.14

// Conversion to boolean
const valeurBool = Boolean(1); // true
// false for: 0, "", null, undefined, NaN, false

Operators

Arithmetic Operators

const a = 10;
const b = 3;

const addition = a + b; // 13
const soustraction = a - b; // 7
const multiplication = a * b; // 30
const division = a / b; // 3.3333...
const modulo = a % b; // 1 (remainder of the division)
const puissance = a ** b; // 1000 (ES2016)

// Increment and decrement
let compteur = 0;
compteur++; // compteur = 1
compteur--; // compteur = 0

Comparison Operators

const a = 10;
const b = "10";

// Equality (with type coercion)
console.log(a == b); // true

// Strict equality (without coercion)
console.log(a === b); // false

// Inequality (with coercion)
console.log(a != b); // false

// Strict inequality (without coercion)
console.log(a !== b); // true

// Comparisons
console.log(a > 5); // true
console.log(a <= 10); // true

Logical Operators

const x = true;
const y = false;

// Logical AND
console.log(x && y); // false

// Logical OR
console.log(x || y); // true

// Logical NOT
console.log(!x); // false

// Short-circuiting (useful for default values)
const nom = null;
const nomAffiche = nom || "Utilisateur inconnu"; // "Utilisateur inconnu"

Nullish Coalescing Operator (ES2020)

const valeur = null;
const resultat = valeur ?? "Valeur par défaut"; // "Valeur par défaut"
// Different from || because it only uses the default value if the value is null or undefined

Optional Chaining Operator (ES2020)

const utilisateur = {
    profil: {
        // adresse: { ville: "Paris" }
    }
};

// Without optional chaining (risk of error)
// const ville = utilisateur.profil.adresse.ville; // Error!

// With optional chaining
const ville = utilisateur.profil?.adresse?.ville; // undefined

Spread Operator

// For arrays
const tab1 = [1, 2, 3];
const tab2 = [...tab1, 4, 5]; // [1, 2, 3, 4, 5]

// For objects
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }

Destructuring (ES6)

Destructuring lets you extract values from arrays or objects concisely:

// Array destructuring
const nombres = [1, 2, 3, 4, 5];
const [premier, deuxieme, ...reste] = nombres;
console.log(premier); // 1
console.log(deuxieme); // 2
console.log(reste); // [3, 4, 5]

// Object destructuring
const personne = { prenom: "Alice", nom: "Dupont", age: 30 };
const { prenom, age, profession = "Inconnue" } = personne;
console.log(prenom); // "Alice"
console.log(age); // 30
console.log(profession); // "Inconnue" (default value)

// Renaming properties
const { prenom: firstName } = personne;
console.log(firstName); // "Alice"

// Nested destructuring
const utilisateur = {
    id: 1,
    infos: {
        nom: "Durand",
        contact: {
            email: "durand@example.com"
        }
    }
};
const { infos: { contact: { email } } } = utilisateur;
console.log(email); // "durand@example.com"

Control Structures

JavaScript offers the usual control structures, with a few modern particularities.

Conditionals

// if, else if, else
const age = 18;

if (age < 18) {
    console.log("Mineur");
} else if (age === 18) {
    console.log("Tout juste majeur");
} else {
    console.log("Majeur");
}

// Ternary operator
const statut = age >= 18 ? "majeur" : "mineur";

Loops

// Classic for
for (let i = 0; i < 5; i++) {
    console.log(i); // 0, 1, 2, 3, 4
}

// for...of (to iterate over the values of an iterable)
const fruits = ["pomme", "banane", "cerise"];
for (const fruit of fruits) {
    console.log(fruit);
}

// for...in (to iterate over the properties of an object)
const personne = { nom: "Dupont", prenom: "Jean", age: 30 };
for (const prop in personne) {
    console.log(`${prop}: ${personne[prop]}`);
}

// while
let compteur = 0;
while (compteur < 5) {
    console.log(compteur);
    compteur++;
}

// do...while
let i = 0;
do {
    console.log(i);
    i++;
} while (i < 5);

Switch

const jour = "Lundi";

switch (jour) {
    case "Lundi":
        console.log("Début de semaine");
        break;
    case "Mercredi":
        console.log("Milieu de semaine");
        break;
    case "Vendredi":
        console.log("Fin de semaine");
        break;
    default:
        console.log("Autre jour");
}

Basic Input and Output

Console

// Output
console.log("Message simple");
console.info("Information");
console.warn("Avertissement");
console.error("Erreur");

// Formatted output
console.log("Nom: %s, Âge: %d", "Alice", 30);

// Grouping
console.group("Détails utilisateur");
console.log("Nom: Alice");
console.log("Âge: 30");
console.groupEnd();

// Table
console.table([
    { nom: "Alice", age: 25 },
    { nom: "Bob", age: 30 }
]);

// Measuring time
console.time("Timer");
// Long-running operations...
console.timeEnd("Timer"); // Displays the elapsed time

User Interaction (Browser)

// Display a message
alert("Attention !");

// Ask for confirmation
const confirmation = confirm("Êtes-vous sûr ?");
if (confirmation) {
    console.log("L'utilisateur a confirmé");
}

// Ask for input
const nom = prompt("Quel est votre nom ?", "Utilisateur");
console.log(`Bonjour, ${nom}`);

Complete Example

Here is an example that uses several of the concepts we have learned:

// Program that calculates the average of a list of numbers

// Define an arrow function to calculate the average
const calculerMoyenne = (nombres) => {
    if (nombres.length === 0) return 0;
    const somme = nombres.reduce((acc, val) => acc + val, 0);
    return somme / nombres.length;
};

// Function to compare a number to the average
const comparerAvecMoyenne = (nombre, moyenne) => {
    if (nombre > moyenne) return "supérieur à";
    if (nombre < moyenne) return "inférieur à";
    return "égal à";
};

// Main program
try {
    // In a real environment, these values could come from a user interface
    const nombres = [15, 20, 25, 10, 30];
    
    // Display the numbers
    console.log("Nombres:", nombres.join(", "));
    
    // Calculate and display the average
    const moyenne = calculerMoyenne(nombres);
    console.log(`La moyenne est: ${moyenne.toFixed(2)}`);
    
    // Compare each number to the average
    console.log("\nComparaison avec la moyenne:");
    nombres.forEach((nombre, index) => {
        const relation = comparerAvecMoyenne(nombre, moyenne);
        console.log(`Nombre ${index + 1} (${nombre}) est ${relation} la moyenne.`);
    });
    
    // Filter the numbers greater than the average
    const nombresSuperieurs = nombres.filter(nombre => nombre > moyenne);
    console.log(`\nNombres supérieurs à la moyenne: ${nombresSuperieurs.join(", ")}`);
    
} catch (erreur) {
    console.error("Une erreur est survenue:", erreur.message);
}

Key Differences from Other Languages

If you know other programming languages, here are some notable differences in JavaScript:

  1. Dynamic typing: There’s no need to declare types; they are determined at runtime.

  2. First-class functions: Functions can be assigned to variables, passed as arguments, and returned by other functions.

  3. Prototypes vs. classes: JavaScript uses a prototype-based system, although class syntax was introduced in ES6.

  4. Hoisting: Variable and function declarations are “hoisted” to the top of their scope.

  5. Events and callbacks: JavaScript relies heavily on callbacks and promises to handle asynchronous code.

  6. Loose vs. strict equality: == performs type coercion, while === does not.

Best Practices

To write clean, maintainable modern JavaScript:

  1. Use const by default, use let if you need to reassign, and avoid var.

  2. Prefer arrow functions for short functions and callbacks.

  3. Use destructuring to extract values from objects or arrays.

  4. Use template literals for multiline strings or strings with interpolation.

  5. Avoid loose comparisons (==, !=); prefer strict comparisons (===, !==).

  6. Use default parameters and spread operators.

  7. Adopt modern array methods like map, filter, and reduce instead of traditional loops when appropriate.

  8. Handle asynchronous code properly with Promises and async/await (which we’ll cover in an upcoming tutorial).

Practice Exercises

To solidify your knowledge, try these exercises:

  1. Write a function that takes an array of numbers and returns the sum of the even numbers.

  2. Create an object representing a book with properties such as title and author, and a method to display this information.

  3. Write a function that takes a string and returns an object containing the number of occurrences of each character.

  4. Create a function that converts a temperature from Celsius to Fahrenheit or vice versa, depending on a mode parameter.

  5. Use destructuring to swap the values of two variables without using a temporary variable.

Conclusion

In this tutorial, we explored the fundamentals of modern JavaScript:

  • The different ways to declare variables (let, const, var)
  • Data types (primitive and reference)
  • Operators (arithmetic, comparison, logical)
  • Destructuring and spread operators
  • Control structures (conditionals and loops)
  • Basic input/output

These concepts are the foundation on which you’ll build your understanding of modern JavaScript. As you progress, you’ll discover how these elements fit together to create dynamic, interactive web applications.

In the next tutorial, we’ll explore modern functions and their new features.


Need to review the basics? Check out our introductory tutorial.

Ready to continue? Move on to the next tutorial on functions.

Comments

Comments are powered by GitHub Discussions

Sign in with GitHub to join the discussion

Link copied!