Comment détecter un objet vide en JavaScript ?
Publié le
Un objet vide en JavaScript, ça paraît simple : {},
pas de propriétés, rien dedans. Mais le détecter proprement est une source régulière
d'erreurs. Est-ce que l'objet existe vraiment ? Est-ce qu'il n'est pas
null ou undefined ?
Et si certaines propriétés sont présentes mais valent
undefined ? Voici les différentes méthodes pour
vérifier qu'un objet est vide, leurs limites, et comment choisir la bonne selon votre
contexte.
D'abord : vérifier que l'objet existe bien
Avant de tester si un objet est vide, il faut s'assurer qu'il existe. En JavaScript,
accéder aux propriétés d'une valeur null ou
undefined lève immédiatement une erreur. C'est le
premier risque à écarter.
// ❌ Ça plante : TypeError: Cannot convert undefined or null to object
Object.keys(utilisateur);
Avant tout test "est-il vide ?", ajoutez donc une garde sur l'existence de l'objet :
if (obj === null || obj === undefined) {
return true; // ou false selon votre logique métier
}
return Object.keys(obj).length === 0;
}
typeof null retourne
"object" en JavaScript, c'est un bug historique du
langage qui ne sera jamais corrigé. Ne vous fiez pas à
typeof pour distinguer un vrai objet de
null. Utilisez toujours un test strict
=== null.
La méthode recommandée : Object.keys()
C'est aujourd'hui la solution la plus lisible, la plus directe et la mieux supportée
pour détecter un objet vide. Object.keys() retourne un
tableau contenant les noms de toutes les propriétés propres et énumérables de l'objet.
Si ce tableau est vide, l'objet l'est aussi.
const objPlein = { nom: 'Alice', age: 30 };
Object.keys(objVide).length === 0; // true → objet vide
Object.keys(objPlein).length === 0; // false → objet non vide
Simple, expressif, et performant pour la grande majorité des cas. C'est la méthode à retenir en premier choix.
Les variantes : Object.values() et
Object.entries()
Le même raisonnement s'applique avec
Object.values() (tableau des valeurs) et
Object.entries() (tableau des paires clé/valeur). Les
trois méthodes renvoient un tableau vide sur un objet vide, donc le test
.length === 0 fonctionne de la même façon.
Object.keys(obj).length === 0; // true
Object.values(obj).length === 0; // true
Object.entries(obj).length === 0; // true
En pratique, Object.keys() est préféré parce qu'il est
légèrement plus performant, il ne lit que les noms de propriétés, sans accéder à leurs
valeurs.
L'approche avec for...in
Avant ES6 et l'arrivée de Object.keys(), la façon
classique de tester un objet vide était de tenter d'itérer dessus avec une boucle
for...in. Si la boucle ne s'exécute pas une seule
fois, l'objet est vide.
for (const cle in obj) {
if (Object.prototype.hasOwnProperty.call(obj, cle)) {
return false; // au moins une propriété propre → pas vide
}
}
return true;
}
Notez la vérification avec hasOwnProperty :
for...in remonte aussi dans la chaîne de prototypes et
peut énumérer des propriétés héritées. Sans ce filtre, un objet qui n'a aucune propriété
propre mais qui hérite de propriétés énumérables serait considéré à tort comme non vide.
Object.keys() à
for...in.
La boucle for...in sans filtre
hasOwnProperty est une source classique de bugs.
Object.keys() ne retourne que les propriétés propres
et énumérables, ce qui est généralement ce qu'on veut. Réservez
for...in aux cas où vous avez besoin d'itérer sur les
propriétés héritées.
L'approche avec JSON.stringify()
Une autre méthode qu'on voit régulièrement consiste à sérialiser l'objet en JSON et à
comparer le résultat à la chaîne "{}".
JSON.stringify({ a: 1 }) === '{}'; // false
Ça fonctionne dans les cas simples, mais cette approche a des limites importantes qu'il faut connaître.
Les pièges de JSON.stringify()
JSON.stringify() ignore silencieusement certaines
valeurs : les propriétés dont la valeur est undefined,
les fonctions, et les symboles. Un objet qui contient ces types de valeurs sera
sérialisé en "{}" alors qu'il n'est pas techniquement
vide.
action: function() {},
valeur: undefined,
cle: Symbol('id')
};
JSON.stringify(obj) === '{}'; // true, mais l'objet a 3 propriétés !
Object.keys(obj).length === 0; // false, réponse correcte
De plus, sérialiser un objet volumineux juste pour tester s'il est vide est inutilement
coûteux. Object.keys() est bien plus efficace.
Les propriétés héritées et les prototypes
Object.keys() ne retourne que les propriétés
propres et énumérables de l'objet, pas celles héritées via le prototype. Dans
la quasi-totalité des cas, c'est le comportement voulu. Mais si vous travaillez avec des
objets créés via une classe ou Object.create(), sachez
que les méthodes héritées ne sont pas comptabilisées.
saluer() { return 'Bonjour'; }
}
const u = new Utilisateur();
Object.keys(u).length === 0; // true → pas de propriétés propres
// mais u.saluer() existe bien, via le prototype
Un objet instance sans propriétés propres sera donc détecté comme vide par
Object.keys(). C'est souvent correct (on teste les
données, pas les méthodes), mais il faut en être conscient.
Les propriétés non énumérables
En JavaScript, les propriétés peuvent être marquées comme non énumérables via
Object.defineProperty(). Ces propriétés sont
invisibles pour Object.keys(),
for...in et
JSON.stringify(). Si vous avez besoin d'inclure les
propriétés non énumérables dans votre test, utilisez
Object.getOwnPropertyNames().
Object.defineProperty(obj, 'secret', {
value: 42,
enumerable: false
});
Object.keys(obj).length === 0; // true, n'en tient pas compte
Object.getOwnPropertyNames(obj).length === 0; // false, la voit
Ce cas est rare dans du code applicatif courant, mais c'est une distinction utile à connaître si vous travaillez avec des bibliothèques tierces ou des objets créés de façon non conventionnelle.
Créer une fonction utilitaire réutilisable
Plutôt que de répéter ce test partout dans votre code, le bon réflexe est d'encapsuler
la logique dans une fonction qui gère tous les cas :
null, undefined,
valeur non-objet, et objet réellement vide.
function estObjetVide(valeur) {
if (valeur === null || valeur === undefined) {
return false;
}
if (typeof valeur !== 'object' || Array.isArray(valeur)) {
return false;
}
return Object.keys(valeur).length === 0;
}
estObjetVide({}); // true
estObjetVide({ a: 1 }); // false
estObjetVide(null); // false
estObjetVide([]); // false
estObjetVide('texte'); // false
Notez le test sur Array.isArray() : un tableau vide
[] est de type
"object", mais ce n'est pas un objet vide au sens où
on l'entend généralement. Ce filtre évite les faux positifs.
utils.js ou
helpers.js) et importez-la là où vous en avez besoin.
Évitez de réimplémenter ce test en ligne à chaque fois : la cohérence du comportement
dans toute l'application dépend d'une seule source de vérité.
Lever une alerte ou une erreur quand un objet est vide
Détecter un objet vide n'a de valeur que si l'on fait quelque chose avec cette information. Selon le contexte, réponse d'une API, paramètre d'une fonction, configuration chargée depuis le localStorage, la réaction attendue varie.
Dans une réponse d'API
Quand vous attendez des données depuis un serveur, une réponse
{} n'est souvent pas une erreur technique mais un cas
métier à traiter : ressource introuvable, accès refusé, résultat vide.
const reponse = await fetch(`/api/utilisateurs/${id}`);
const donnees = await reponse.json();
if (estObjetVide(donnees)) {
console.warn(`Profil introuvable pour l'id ${id}`);
return null;
}
return donnees;
}
Dans une fonction utilitaire ou une bibliothèque interne
Si une fonction attend impérativement un objet non vide pour fonctionner, il vaut mieux lever une erreur explicite plutôt que de laisser planter silencieusement plus loin dans le code.
if (estObjetVide(params)) {
throw new Error('construireUrl attend un objet de paramètres non vide.');
}
return '?' + new URLSearchParams(params).toString();
}
construireUrl({}); // ❌ Error: construireUrl attend...
construireUrl({ page: 2 }); // ✓ "?page=2"
throw new Error() avec un message clair est infiniment
plus facile à déboguer qu'une valeur undefined qui
remonte cinq niveaux plus haut dans la pile d'appels. Validez les entrées en début de
fonction.
Dans l'interface utilisateur
Côté UI, un objet vide signifie souvent qu'il n'y a rien à afficher. Plutôt que de laisser un composant rendu vide ou cassé, on affiche un état explicite.
const zone = document.getElementById('zone-resultat');
if (estObjetVide(resultat)) {
zone.textContent = 'Aucun résultat trouvé.';
return;
}
// On peut travailler avec resultat en toute sécurité
zone.innerHTML = `<p>${resultat.titre}</p>`;
}
Propriétés présentes mais valant undefined ou
null
Une situation souvent source de confusion : un objet qui a des propriétés, mais dont les
valeurs sont undefined ou
null. Cet objet n'est pas vide au
sens strict, ses clés existent.
Object.keys(obj).length === 0; // false → 2 clés présentes
Si votre besoin est de détecter un objet "sans données utiles" (toutes les valeurs sont vides ou absentes), il faut compléter le test :
if (!obj || typeof obj !== 'object') return true;
return Object.values(obj).every(
v => v === null || v === undefined || v === ''
);
}
sansValeurUtile({ nom: null, age: undefined }); // true
sansValeurUtile({ nom: 'Alice', age: null }); // false
Cette logique est plus proche d'une validation métier que d'un simple test d'objet vide.
Adaptez les conditions dans le .every() selon ce que
vous considérez comme "sans valeur utile" dans votre contexte.
Synthèse
| Situation | Ce qu'on utilise |
|---|---|
| Tester un objet vide dans le cas général | Object.keys(obj).length === 0 |
| Avant tout test, vérifier que l'objet existe |
Vérification explicite === null /
=== undefined
|
| Éviter les faux positifs avec les tableaux |
Object.keys() +
Array.isArray()
|
| Inclure les propriétés non énumérables |
Object.getOwnPropertyNames(obj).length === 0
|
| Tester si toutes les valeurs sont vides (null, undefined…) | Object.values(obj).every(...) |
| Lever une erreur si l'objet est vide |
Garde en début de fonction + throw new Error()
|
Pour la très grande majorité des cas,
Object.keys(obj).length === 0 précédé d'une
vérification de l'existence de l'objet est tout ce dont vous avez besoin. Les variantes
avec getOwnPropertyNames() ou
Object.values().every() sont à réserver aux besoins
spécifiques où la sémantique de "vide" est différente.