Implémentations manuelles pour entretiens techniques

Dessiner un secteur circulaire en CSS

/* Cercle de base */
.cercle-base {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    background: #e74c3c;
    position: relative;
}

/* Premier masque pour créer le secteur */
.masque-premier {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 50px;
    background: white;
    transform-origin: 50px 50px;
    transform: rotate(75deg);
}

/* Second masque avec rotation différente */
.masque-second {
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 50px;
    background: white;
    transform-origin: 50px 50px;
    transform: rotate(150deg);
}

Chargement paresseux des images

document.addEventListener('DOMContentLoaded', () => {
    const imagesParesseuses = Array.from(document.querySelectorAll('img[data-src]'));
    
    if (!('IntersectionObserver' in window)) {
        // Fallback pour les navigateurs anciens
        imagesParesseuses.forEach(img => {
            img.src = img.dataset.src;
        });
        return;
    }
    
    const observateur = new IntersectionObserver((entrees) => {
        entrees.forEach(entree => {
            if (entree.isIntersecting) {
                const image = entree.target;
                image.src = image.dataset.src;
                observateur.unobserve(image);
            }
        });
    });
    
    imagesParesseuses.forEach(img => observateur.observe(img));
});

Glisser-déposer de la souris

const elementDeplacable = document.querySelector('.deplacable');
let decalageX, decalageY;

elementDeplacable.addEventListener('mousedown', debutDeplacement);

function debutDeplacement(evenement) {
    decalageX = evenement.clientX - elementDeplacable.offsetLeft;
    decalageY = evenement.clientY - elementDeplacable.offsetTop;
    
    document.addEventListener('mousemove', deplacerElement);
    document.addEventListener('mouseup', arreterDeplacement);
}

function deplacerElement(evenement) {
    let nouvelleGauche = evenement.clientX - decalageX;
    let nouveauHaut = evenement.clientY - decalageY;
    
    // Limites de l'écran
    const limiteDroite = window.innerWidth - elementDeplacable.offsetWidth;
    const limiteBas = window.innerHeight - elementDeplacable.offsetHeight;
    
    nouvelleGauche = Math.max(0, Math.min(nouvelleGauche, limiteDroite));
    nouveauHaut = Math.max(0, Math.min(nouveauHaut, limiteBas));
    
    elementDeplacable.style.left = `${nouvelleGauche}px`;
    elementDeplacable.style.top = `${nouveauHaut}px`;
}

function arreterDeplacement() {
    document.removeEventListener('mousemove', deplacerElement);
    document.removeEventListener('mouseup', arreterDeplacement);
}

Addition de nombres flottants

function multiplicationPrecise(premier, second) {
    const chainePremier = premier.toString();
    const chaineSecond = second.toString();
    
    let decimales = 0;
    try { decimales += chainePremier.split('.')[1].length; } catch (e) {}
    try { decimales += chaineSecond.split('.')[1].length; } catch (e) {}
    
    const nombreEntierPremier = Number(chainePremier.replace('.', ''));
    const nombreEntierSecond = Number(chaineSecond.replace('.', ''));
    
    return (nombreEntierPremier * nombreEntierSecond) / Math.pow(10, decimales);
}

// Exemple d'utilisation
console.log(multiplicationPrecise(0.1, 0.2)); // 0.02

Planificateur de tâches concurrentes

class PlanificateurTaches {
    constructor(maxSimultanees = 3) {
        this.maximum = maxSimultanees;
        this.enCours = 0;
        this.fileAttente = [];
    }
    
    ajouter(tache) {
        return new Promise((resolution, rejet) => {
            const travail = { tache, resolution, rejet };
            this.fileAttente.push(travail);
            this.executer();
        });
    }
    
    async executer() {
        while (this.fileAttente.length > 0 && this.enCours < this.maximum) {
            this.enCours++;
            const travail = this.fileAttente.shift();
            
            try {
                const resultat = await travail.tache();
                travail.resolution(resultat);
            } catch (erreur) {
                travail.rejet(erreur);
            } finally {
                this.enCours--;
                this.executer();
            }
        }
    }
}

// Exemple d'utilisation
const planificateur = new PlanificateurTaches(2);

const simulerRequete = (delai, identifiant) => {
    return new Promise(resolution => {
        setTimeout(() => {
            console.log(`Tâche ${identifiant} terminée`);
            resolution(identifiant);
        }, delai);
    });
};

planificateur.ajouter(() => simulerRequete(1000, 'A'));
planificateur.ajouter(() => simulerRequete(500, 'B'));
planificateur.ajouter(() => simulerRequete(800, 'C'));
planificateur.ajouter(() => simulerRequete(300, 'D'));

Chaînage asynchrone avec temporisation

class Actionneur {
    constructor() {
        this.chaine = Promise.resolve();
    }
    
    executer(action) {
        this.chaine = this.chaine.then(() => action());
        return this;
    }
    
    attendre(secondes) {
        return this.executer(() => 
            new Promise(resolution => 
                setTimeout(resolution, secondes * 1000)
            )
        );
    }
    
    afficher(message) {
        return this.executer(() => {
            console.log(message);
            return Promise.resolve();
        });
    }
}

// Exemple d'utilisation
const actionneur = new Actionneur();
actionneur
    .afficher('Début')
    .attendre(2)
    .afficher('Après 2 secondes')
    .attendre(3)
    .afficher('Fin');

Modèles de conception

Adaptateur

// Interface incompatible avec le système
const cartographieNouvelle = {
    dessiner() {
        console.log('Rendu de la nouvelle carte');
    }
};

// Adaptateur pour l'interface attendue
const adaptateurCarte = {
    afficher() {
        cartographieNouvelle.dessiner();
    }
};

// Le client utilise l'adaptateur comme s'il utilisait l'ancienne interface
function utiliserCarte(adaptateur) {
    adaptateur.afficher();
}

utiliserCarte(adaptateurCarte);

Observateur (Éditeur-Abonné)

class BusEvenements {
    constructor() {
        this.abonnes = new Map();
    }
    
    sAbonner(nomEvenement, callback) {
        if (!this.abonnes.has(nomEvenement)) {
            this.abonnes.set(nomEvenement, new Set());
        }
        this.abonnes.get(nomEvenement).add(callback);
        
        // Retourne une fonction de désabonnement
        return () => this.abonnes.get(nomEvenement)?.delete(callback);
    }
    
    publier(nomEvenement, ...donnees) {
        const callbacks = this.abonnes.get(nomEvenement);
        if (callbacks) {
            callbacks.forEach(callback => callback(...donnees));
        }
    }
    
    sAbonnerUneFois(nomEvenement, callback) {
        const desabonnement = this.sAbonner(nomEvenement, (...args) => {
            callback(...args);
            desabonnement();
        });
        return desabonnement;
    }
}

// Exemple d'utilisation
const bus = new BusEvenements();

const desabonnement = bus.sAbonner('message', contenu => {
    console.log('Message reçu:', contenu);
});

bus.publier('message', 'Bonjour le monde!');

desabonnement(); // Se désabonner

Singleton

class GestionnaireConfig {
    static instance = null;
    
    constructor() {
        if (GestionnaireConfig.instance) {
            return GestionnaireConfig.instance;
        }
        
        this.parametres = {};
        GestionnaireConfig.instance = this;
    }
    
    definir(cle, valeur) {
        this.parametres[cle] = valeur;
        return this;
    }
    
    obtenir(cle) {
        return this.parametres[cle];
    }
}

// Partout dans l'application, on obtient la même instance
const config1 = new GestionnaireConfig();
config1.definir('langue', 'fr');

const config2 = new GestionnaireConfig();
console.log(config2.obtenir('langue')); // 'fr' - même instance

Distribution aléatoire de mnotants

function distribuerMontant(total, nombrePersonnes) {
    if (total < nombrePersonnes) {
        throw new Error('Montant insuffisant');
    }
    
    const resultats = [];
    let restant = total;
    let personnesRestantes = nombrePersonnes;
    
    // Distribution aléatoire pour n-1 personnes
    for (let i = 0; i < nombrePersonnes - 1; i++) {
        // Minimum 1 centime, maximum (restant - personnesRestantes + 1)
        const maximum = restant - personnesRestantes + 1;
        const montant = Math.floor(Math.random() * maximum) + 1;
        
        resultats.push(montant);
        restant -= montant;
        personnesRestantes--;
    }
    
    // La dernière personne reçoit le reste
    resultats.push(restant);
    
    // Mélanger pour plus d'équité
    return melangerTableau(resultats);
}

function melangerTableau(tableau) {
    const copie = [...tableau];
    for (let i = copie.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [copie[i], copie[j]] = [copie[j], copie[i]];
    }
    return copie;
}

// Exemple d'utilisation
const montants = distribuerMontant(1000, 5); // 10€ pour 5 personnes
console.log(montants.map(m => (m / 100).toFixed(2) + '€'));

Formatage de nombres avec séparateurs

function formaterNombre(nombre) {
    const [entier, decimal] = nombre.toString().split('.');
    let resultat = '';
    let compteur = 0;
    
    // Parcourir de droite à gauche
    for (let i = entier.length - 1; i >= 0; i--) {
        compteur++;
        resultat = entier[i] + resultat;
        
        // Ajouter un séparateur tous les 3 chiffres
        if (compteur % 3 === 0 && i !== 0) {
            resultat = ' ' + resultat;
        }
    }
    
    return decimal ? `${resultat},${decimal}` : resultat;
}

// Exemples
console.log(formaterNombre(1234567.89)); // "1 234 567,89"
console.log(formaterNombre(100000)); // "100 000"

Algorithmes de tri

Tri à bulles optimisé

function triABullesOptimise(tableau) {
    const n = tableau.length;
    let permutationEffectuee = true;
    
    for (let i = 0; i < n - 1 && permutationEffectuee; i++) {
        permutationEffectuee = false;
        
        for (let j = 0; j < n - 1 - i; j++) {
            if (tableau[j] > tableau[j + 1]) {
                // Échange des éléments
                [tableau[j], tableau[j + 1]] = [tableau[j + 1], tableau[j]];
                permutationEffectuee = true;
            }
        }
    }
    
    return tableau;
}

Tri par fusion

function triParFusion(tableau) {
    if (tableau.length <= 1) return tableau;
    
    const milieu = Math.floor(tableau.length / 2);
    const gauche = tableau.slice(0, milieu);
    const droite = tableau.slice(milieu);
    
    return fusionner(
        triParFusion(gauche),
        triParFusion(droite)
    );
}

function fusionner(gauche, droite) {
    let i = 0, j = 0;
    const resultat = [];
    
    while (i < gauche.length && j < droite.length) {
        if (gauche[i] <= droite[j]) {
            resultat.push(gauche[i++]);
        } else {
            resultat.push(droite[j++]);
        }
    }
    
    return resultat
        .concat(gauche.slice(i))
        .concat(droite.slice(j));
}

Tri rapide (Quicksort)

function triRapide(tableau, debut = 0, fin = tableau.length - 1) {
    if (debut < fin) {
        const pivotIndex = partitionner(tableau, debut, fin);
        triRapide(tableau, debut, pivotIndex - 1);
        triRapide(tableau, pivotIndex + 1, fin);
    }
    return tableau;
}

function partitionner(tableau, debut, fin) {
    // Choisir un pivot aléatoire
    const pivotAleatoire = debut + Math.floor(Math.random() * (fin - debut + 1));
    [tableau[debut], tableau[pivotAleatoire]] = [tableau[pivotAleatoire], tableau[debut]];
    
    const pivot = tableau[debut];
    let gauche = debut + 1;
    let droite = fin;
    
    while (gauche <= droite) {
        while (gauche <= droite && tableau[gauche] <= pivot) gauche++;
        while (gauche <= droite && tableau[droite] > pivot) droite--;
        
        if (gauche < droite) {
            [tableau[gauche], tableau[droite]] = [tableau[droite], tableau[gauche]];
        }
    }
    
    [tableau[debut], tableau[droite]] = [tableau[droite], tableau[debut]];
    return droite;
}

Conversion tableau arborescent

const donneesPlates = [
    { id: 1, parent: null, libelle: 'Racine' },
    { id: 2, parent: 1, libelle: 'Enfant A' },
    { id: 3, parent: 1, libelle: 'Enfant B' },
    { id: 4, parent: 2, libelle: 'Petit-enfant A1' },
    { id: 5, parent: 2, libelle: 'Petit-enfant A2' },
];

function construireArborescence(elements, parentId = null) {
    const noeuds = elements.filter(el => el.parent === parentId);
    
    return noeuds.map(noeud => ({
        ...noeud,
        enfants: construireArborescence(elements, noeud.id)
    }));
}

// Exemple d'utilisation
const arbre = construireArborescence(donneesPlates);
console.log(JSON.stringify(arbre, null, 2));

Parcours d'arbre DOM

function parcourirLargeur(racine) {
    if (!racine) return;
    
    const file = [racine];
    const etiquettes = [];
    
    while (file.length > 0) {
        const noeudCourant = file.shift();
        
        if (noeudCourant.tagName) {
            etiquettes.push(noeudCourant.tagName.toLowerCase());
        }
        
        // Ajouter les enfants à la file
        const enfants = Array.from(noeudCourant.children);
        file.push(...enfants);
    }
    
    return etiquettes;
}

// Exemple d'utilisation
// const tousTags = parcourirLargeur(document.body);

Comparaison profonde d'objets

function comparerEnProfondeur(objet1, objet2, visites = new WeakMap()) {
    // Vérification identité stricte
    if (objet1 === objet2) return true;
    
    // Gestion des valeurs nulles/undefined
    if (objet1 == null || objet2 == null) {
        return objet1 === objet2;
    }
    
    // Vérification des types
    if (typeof objet1 !== typeof objet2) return false;
    
    // Détection des références circulaires
    if (visites.has(objet1) && visites.get(objet1) === objet2) {
        return true;
    }
    visites.set(objet1, objet2);
    
    // Comparaison des dates
    if (objet1 instanceof Date && objet2 instanceof Date) {
        return objet1.getTime() === objet2.getTime();
    }
    
    // Comparaison des expressions régulières
    if (objet1 instanceof RegExp && objet2 instanceof RegExp) {
        return objet1.toString() === objet2.toString();
    }
    
    // Comparaison des tableaux
    if (Array.isArray(objet1) && Array.isArray(objet2)) {
        if (objet1.length !== objet2.length) return false;
        
        return objet1.every((element, index) => 
            comparerEnProfondeur(element, objet2[index], visites)
        );
    }
    
    // Comparaison des objets
    const cles1 = Object.keys(objet1);
    const cles2 = Object.keys(objet2);
    
    if (cles1.length !== cles2.length) return false;
    
    return cles1.every(cle => 
        Object.prototype.hasOwnProperty.call(objet2, cle) &&
        comparerEnProfondeur(objet1[cle], objet2[cle], visites)
    );
}

Fonction anti-rebond (debounce)

function antiRebonction(fonction, delai) {
    let temporisateur;
    
    return function(...args) {
        const contexte = this;
        
        clearTimeout(temporisateur);
        temporisateur = setTimeout(() => {
            fonction.apply(contexte, args);
        }, delai);
    };
}

// Exemple d'utilisation
const rechercher = antiRebonction((terme) => {
    console.log('Recherche pour:', terme);
}, 300);

// input.addEventListener('input', e => rechercher(e.target.value));

Fonction d'étranglement (throttle)

function etrangleur(fonction, intervalle) {
    let dernierAppel = 0;
    let temporisateur;
    
    return function(...args) {
        const maintenant = Date.now();
        const delaiRestant = intervalle - (maintenant - dernierAppel);
        
        clearTimeout(temporisateur);
        
        if (delaiRestant <= 0) {
            dernierAppel = maintenant;
            fonction.apply(this, args);
        } else {
            temporisateur = setTimeout(() => {
                dernierAppel = Date.now();
                fonction.apply(this, args);
            }, delaiRestant);
        }
    };
}

// Exemple d'utilisation avec scroll
// window.addEventListener('scroll', etrangleur(() => {
//     console.log('Position:', window.scrollY);
// }, 200));

Copie superifcielle et profonde

// Copie superficielle
function copieSuperficielle(objet) {
    if (typeof objet !== 'object' || objet === null) {
        return objet;
    }
    
    return Array.isArray(objet) 
        ? [...objet] 
        : { ...objet };
}

// Copie profonde avec gestion des références circulaires
function copieProfonde(objet, memoire = new WeakMap()) {
    if (typeof objet !== 'object' || objet === null) {
        return objet;
    }
    
    // Vérifier si déjà copié (référence circulaire)
    if (memoire.has(objet)) {
        return memoire.get(objet);
    }
    
    // Créer la copie vide
    const copie = Array.isArray(objet) ? [] : {};
    memoire.set(objet, copie);
    
    // Copier chaque propriété
    for (const cle of Object.keys(objet)) {
        copie[cle] = copieProfonde(objet[cle], memoire);
    }
    
    return copie;
}

// Exemple d'objet avec référence circulaire
const original = { a: 1, b: { c: 2 } };
original.b.d = original; // Référence circulaire

const copie = copieProfonde(original);
console.log(copie.a); // 1
console.log(copie.b.d === copie); // true - référence préservée

Implémentation de promesses

const ETAT_EN_ATTENTE = 'en_attente';
const ETAT_RESOLU = 'resolu';
const ETAT_REJETE = 'rejete';

class PromessePersonnalisee {
    constructor(executeur) {
        this.etat = ETAT_EN_ATTENTE;
        this.valeur = null;
        this.observateurs = [];
        
        try {
            executeur(
                this._resoudre.bind(this),
                this._rejeter.bind(this)
            );
        } catch (erreur) {
            this._rejeter(erreur);
        }
    }
    
    _resoudre(valeur) {
        setTimeout(() => {
            if (this.etat === ETAT_EN_ATTENTE) {
                this.etat = ETAT_RESOLU;
                this.valeur = valeur;
                this._notifierObservateurs();
            }
        });
    }
    
    _rejeter(raison) {
        if (this.etat === ETAT_EN_ATTENTE) {
            this.etat = ETAT_REJETE;
            this.valeur = raison;
            this._notifierObservateurs();
        }
    }
    
    _notifierObservateurs() {
        this.observateurs.forEach(({ quandResolu, quandRejete }) => {
            const executer = this.etat === ETAT_RESOLU ? quandResolu : quandRejete;
            if (typeof executer === 'function') {
                executer(this.valeur);
            }
        });
    }
    
    alors(quandResolu, quandRejete) {
        return new PromessePersonnalisee((resoudre, rejeter) => {
            const observateur = {
                quandResolu: valeur => {
                    try {
                        const resultat = quandResolu(valeur);
                        resoudre(resultat);
                    } catch (erreur) {
                        rejeter(erreur);
                    }
                },
                quandRejete: raison => {
                    try {
                        const resultat = quandRejete(raison);
                        resoudre(resultat);
                    } catch (erreur) {
                        rejeter(erreur);
                    }
                }
            };
            
            if (this.etat === ETAT_EN_ATTENTE) {
                this.observateurs.push(observateur);
            } else {
                setTimeout(() => executer(this.valeur));
            }
        });
    }
    
    static tous(promesses) {
        return new PromessePersonnalisee((resoudre, rejeter) => {
            const resultats = [];
            let compteur = 0;
            
            promesses.forEach((promesse, index) => {
                promesse.alors(
                    valeur => {
                        resultats[index] = valeur;
                        compteur++;
                        if (compteur === promesses.length) {
                            resoudre(resultats);
                        }
                    },
                    rejeter
                );
            });
        });
    }
}

Implémentation de JSON.stringify

function serialiserJSON(donnees) {
    // Gestion des types primitifs
    if (donnees === null || donnees === undefined) {
        return String(donnees);
    }
    
    if (typeof donnees === 'number') {
        return Number.isFinite(donnees) ? String(donnees) : 'null';
    }
    
    if (typeof donnees === 'boolean') {
        return String(donnees);
    }
    
    if (typeof donnees === 'string') {
        return `"${donnees}"`;
    }
    
    // Gestion des fonctions et symboles (ignorés)
    if (typeof donnees === 'function' || typeof donnees === 'symbol') {
        return undefined;
    }
    
    // Gestion des tableaux
    if (Array.isArray(donnees)) {
        const elements = donnees.map(element => 
            serialiserJSON(element) || 'null'
        );
        return `[${elements.join(',')}]`;
    }
    
    // Gestion des objets
    if (typeof donnees === 'object') {
        const proprietes = Object.keys(donnees)
            .filter(cle => typeof donnees[cle] !== 'function' && typeof donnees[cle] !== 'symbol')
            .map(cle => {
                const valeur = serialiserJSON(donnees[cle]);
                if (valeur !== undefined) {
                    return `"${cle}":${valeur}`;
                }
                return null;
            })
            .filter(Boolean);
        
        return `{${proprietes.join(',')}}`;
    }
    
    return String(donnees);
}

// Exemple d'utilisation
console.log(serialiserJSON({ a: 1, b: [2, 3], c: null }));

Implémentation de new

function creerNouvelleInstance(constructeur, ...args) {
    // 1. Créer un nouvel objet avec le prototype du constructeur
    const nouvelObjet = Object.create(constructeur.prototype);
    
    // 2. Appliquer le constructeur à l'objet
    const resultat = constructeur.apply(nouvelObjet, args);
    
    // 3. Retourner l'objet si le constructeur ne retourne pas d'objet
    return (typeof resultat === 'object' && resultat !== null) 
        ? resultat 
        : nouvelObjet;
}

// Exemple d'utilisation
function Personne(nom, age) {
    this.nom = nom;
    this.age = age;
}

Personne.prototype.saluer = function() {
    console.log(`Bonjour, je suis ${this.nom}`);
};

const personne = creerNouvelleInstance(Personne, 'Alice', 30);
personne.saluer(); // "Bonjour, je suis Alice"

Implémentation de call, apply et bind

Function.prototype.appelPersonnalise = function(contexte, ...args) {
    contexte = contexte || globalThis;
    const cleUnique = Symbol('fonctionTemporaire');
    
    contexte[cleUnique] = this;
    const resultat = contexte[cleUnique](...args);
    delete contexte[cleUnique];
    
    return resultat;
};

Function.prototype.applicationPersonnalisee = function(contexte, args) {
    contexte = contexte || globalThis;
    const cleUnique = Symbol('fonctionTemporaire');
    
    contexte[cleUnique] = this;
    const resultat = contexte[cleUnique](...args);
    delete contexte[cleUnique];
    
    return resultat;
};

Function.prototype.liaisonPersonnalisee = function(contexte, ...argsIniciaux) {
    const fonctionOriginale = this;
    
    return function(...argsNouveaux) {
        return fonctionOriginale.apply(
            contexte,
            argsIniciaux.concat(argsNouveaux)
        );
    };
};

File d'attente asynchrone

class FileAttenteAsynchrone {
    constructor(concurrence = 1) {
        this.maximum = concurrence;
        this.enCours = 0;
        this.taches = [];
        this.resultats = [];
    }
    
    ajouter(tacheAsynchrone) {
        return new Promise((resolution, rejet) => {
            this.taches.push({
                executer: tacheAsynchrone,
                resolution,
                rejet
            });
            
            this._traiter();
        });
    }
    
    async _traiter() {
        while (this.taches.length > 0 && this.enCours < this.maximum) {
            this.enCours++;
            
            const tache = this.taches.shift();
            
            try {
                const resultat = await tache.executer();
                tache.resolution(resultat);
                this.resultats.push(resultat);
            } catch (erreur) {
                tache.rejet(erreur);
            } finally {
                this.enCours--;
                this._traiter();
            }
        }
    }
    
    obtenirResultats() {
        return this.resultats;
    }
}

// Exemple d'utilisation
const file = new FileAttenteAsynchrone(2);

file.ajouter(() => new Promise(r => setTimeout(() => r('A'), 1000)));
file.ajouter(() => new Promise(r => setTimeout(() => r('B'), 500)));
file.ajouter(() => new Promise(r => setTimeout(() => r('C'), 800)));

Implémentation de lodash.get

function obtenirValeur(objet, chemin, valeurDefaut = undefined) {
    if (typeof chemin === 'string') {
        chemin = chemin.replace(/\[(\d+)\]/g, '.$1').split('.');
    }
    
    let courant = objet;
    
    for (const segment of chemin) {
        if (courant === null || courant === undefined) {
            return valeurDefaut;
        }
        courant = courant[segment];
    }
    
    return courant !== undefined ? courant : valeurDefaut;
}

// Exemple d'utilisation
const donnees = {
    utilisateur: {
        adresses: [
            { ville: 'Paris', code: '75001' },
            { ville: 'Lyon', code: '69001' }
        ]
    }
};

console.log(obtenirValeur(donnees, 'utilisateur.adresses[1].ville')); // "Lyon"
console.log(obtenirValeur(donnees, 'utilisateur.age', 25)); // 25

Étiquettes: JavaScript ES6 DOM promises Design Patterns

Publié le 9 juillet à 17h02