Quiz : Délices de la déstructuration
Êtes‑vous un maestro du destructuring ?
Ou bien votre Symphonie de la Destruction ?
Ce quiz évaluera votre maîtrise du destructuring en JavaScript : des syntaxes d’objet « basique » au destructuring imbriqué et aux valeurs par défaut. Bonus : questions sur TypeScript et les types inline !
Plongez directement dans l’échauffement – prouvez vos compétences en destructuring ! 👇
Qu’affichera ce code ?
const person = { name: 'Dan Levy', location: 'Cape Town',};const { name, age } = person;console.log(`Name: ${name}, Age: ${age}`);La propriété age n’existe pas sur person, donc age sera undefined. Ce n’est certainement pas Infinity 😅
Cela donne :
Name: Dan Levy, Age: undefinedQue fera ce code ?
const person = [ 'Dan Levy', 'Cape Town' ];const [ name, origin, age ] = person;console.log(`Name: ${name}, Age: ${age}`);La variable age n’est pas présente dans le tableau tuple, donc elle sera undefined.
Cela donne :
Name: Dan Levy, Age: undefinedEt si on faisait de la déstructuration imbriquée ?
'use strict';const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first }, address: { city }, birth: { place },} = person;console.log( `First: ${first}, City: ${place}`,);La propriété birth: { place } n’existe pas sur person, donc elle lèvera une erreur.
Une solution consiste à fournir des valeurs par défaut pour les propriétés imbriquées.
Lors de l’accès aux propriétés imbriquées, soyez prudent, car les erreurs peuvent être difficiles à repérer. De plus, les messages d’erreur varient selon les navigateurs et les plateformes, ce qui complique le débogage.
Dans Chrome moderne : TypeError: Cannot read properties of undefined (reading 'place')
Dans Node, c’est aussi un TypeError parce que JavaScript tente de destructurer place depuis undefined avant même que place ne soit lu.
La formulation exacte varie selon les navigateurs et les environnements d’exécution.
Avec quelques valeurs par défaut, que va‑t‑il faire ?
'use strict';const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first = 'Unknown' }, birth: { place = 'Unknown' },} = person;console.log( `Hi ${first} from ${place}`,);La propriété birth est absente : JavaScript tente donc de déstructurer place depuis undefined. L’erreur est levée avant que la valeur par défaut de place puisse s’appliquer.
TypeErrorLe message exact dépend de l’environnement d’exécution. La valeur par défaut d’une propriété ne traite son absence ou sa valeur undefined qu’une fois l’objet contenant disponible. Utilisez birth: { place = "Unknown" } = {} pour fournir un objet par défaut quand birth est absente ou vaut undefined.
Que fera ce code ?
const person = { name: { first: 'Dan' }, address: { city: 'Denver' },};const { name: { first = 'Unknown' }, birth: { place = 'Unknown' } = {},} = person;
console.log( `Hi ${first} from ${place}`,);La propriété birth n’existe pas sur person, donc elle retombe sur un objet vide = {}. Cela permet d’utiliser la valeur par défaut.
Maintenant, en tant que paramètres de fonction, que fera-t-elle ?
'use strict';function displayUser({ name = "Unknown", age = -1,} = { place: "Unknown" }) { console.log(`Hi ${name} from ${place}`);}displayUser({ name: "Dan" });Cette fonction extrait les propriétés name et age, en utilisant des valeurs par défaut si nécessaire. Dans ce cas, la clé place de l’objet par défaut n’est qu’un bruit, elle n’est pas utilisée dans displayUser().
Le mode strict ne change rien ici : lire la liaison non déclarée place lève une ReferenceError.
Comment les valeurs undefined sont‑elles gérées ?
'use strict';function displayPlace({ name = "N/A", place = "N/A", age = -1,} = { place: "Unknown" }) { console.log(`${place}`);}displayPlace({ name: "Dan" });displayPlace({ name: "Dan", place: undefined });displayPlace({ name: "Dan", place: "Joburg" });L’objet paramètre par défaut { place: "Unknown" } est utilisé si l’argument est omis ou vaut explicitement undefined : displayPlace() et displayPlace(undefined) affichent tous deux Unknown.
Si un objet est fourni, une propriété place absente ou valant undefined utilise sa propre valeur par défaut "N/A". Les valeurs par défaut du paramètre et de la propriété s’appliquent à des niveaux différents.
displayPlace() // UnknowndisplayPlace({ name: "Dan" }) // N/AdisplayPlace({ name: "Dan", place: undefined }) // N/ASemblable au précédent… comment null est‑il géré ?
function displayPlace({ name = "N/A", place = "N/A", age = -1,} = { place: "Unknown" }) { console.log(`${place}`);}displayPlace({ name: "Dan", place: null });displayPlace({ name: "Dan", place: undefined });Au premier appel, place vaut null ; au second, elle vaut undefined. La valeur par défaut de la propriété, "N/A", s’applique quand place est absente ou vaut undefined, même si l’objet est fourni. null ne déclenche pas cette valeur par défaut : les sorties sont donc null et N/A.
Place à TypeScript
Maintenant en TypeScript… que fera-t-il ?
'use strict';function displayPlace( { name = 'N/A', place = 'N/A', }: { name: string; place: string; age: number; },) { console.log(`${place}`);}displayPlace({ name: 'Dan', place: null });TypeScript signale une erreur parce que place est typé comme string, mais l’appel passe null. L’appel omet également la propriété requise age.
Si vous ignorez les erreurs de type, l’exécution du code affichera null dans la console.
Essayons un peu de renommage/assignation…
'use strict';function displayPlace({ name = 'N/A', place: location = 'N/A',}: { name: string; place: string; age?: number;}) { console.log(`${location}`);}displayPlace({ name: 'Dan', place: 'Denver' });Cela affichera Denver dans la console. La propriété place est renommée en location dans la signature de la fonction. C’est un schéma courant (renommer des propriétés lors de la déstructuration) lorsqu’on adapte des structures de données tierces.
Repérez l’erreur de type :
function greet({ name: {first = "N/A", last = "N/A"}, birth: {place = "N/A"} = {}, age = -1,}: { name: {first?: string, last?: string}; birth: {place?: string}; age: number;}) { console.log(`Hi ${first} ${last} from ${place}`);}greet({ name: {first: 'Dan'} });L’erreur se trouve dans la signature de la fonction greet. Les propriétés age et birth sont absentes dans l’objet passé, elles doivent donc être optionnelles dans la définition du type.
Même si la propriété birth est destructurée avec une valeur par défaut, la définition du type exige qu’elle soit présente. Pour marquer une propriété comme optionnelle en TypeScript, il faut utiliser l’opérateur ?.
Notez que birth?: { place?: string } n’est pas équivalent à birth: { place?: string } | undefined.
Maintenant avec affectation (notez les variables f, l et p)
'use strict';function greet( { name: {first: f = "N/A", last: l = "N/A"}, birth: {place: p = "N/A"} = {}, age = -1, }: { name: {first?: string, last?: string}; birth?: {place?: string}; age?: number; }) { console.log(`Hi ${f} ${l} from ${place}`); // What will 👆 do?}greet({ name: {first: 'Dan', last: 'Levy'}, birth: {place: 'Cape Town'},});Une autre erreur ! Vous commencez à deviner, n’est-ce pas ?!
Il est difficile de lire les couches de déstructuration, avec des valeurs par défaut, l’affectation et les types !
Dès que place est réassigné à la variable p, il n’est plus défini dans la portée de l’instruction console.log.
console.log(`Hi ${f} ${l} from ${place}`); // ❌// to:console.log(`Hi ${f} ${l} from ${p}`); // ✅Ça faisait beaucoup de déstructuration, de valeurs par défaut, d’imbrication, d’affectation et de TypeScript ! 🤯
J’espère que cela vous a plu !
Vous en voulez encore ? Bien sûr ! Découvrez ma collection de quiz pour d’autres défis.
