Écrit par Lewis Cianci✏️
Alors, vous êtes un développeur JavaScript ? C'est agréable à entendre : que pensez-vous que ce code renvoie ? Et oui, c'est une question piège :
function returnSomething() { return { name: 'JavaScript Expert' contactMethod: 'Shine batsign at sky' } }
Dans presque tous les autres langages — C#, Java, la liste est longue — nous récupérerions l'objet avec JavaScript Expert. Et on pourrait penser qu’en JavaScript, on obtiendrait le même résultat.
Cependant, faites-moi plaisir et insérez ceci dans votre console de développement, puis exécutez la fonction. Presque incroyable, il revient indéfini.
Travailler en tant que développeur de logiciels signifie que vous êtes responsable du fonctionnement de votre application, qu'elle fonctionne bien ou mal. L’une des principales contraintes réside dans les outils que vous décidez d’utiliser. Si vous comprenez ce que vous utilisez, vous ferez, espérons-le, de bons choix dans la façon dont vous concevez votre logiciel.
JavaScript est unique car c'est le langage de prédilection de nombreux nouveaux développeurs de logiciels. Vous souhaitez écrire une application mobile ? Utilisez simplement React Native et JavaScript. Une application de bureau ? Réagissez natif et JavaScript. Une fonction cloud à exécuter quelque part ? Node.js et, vous l'aurez deviné, JavaScript.
Cependant, en raison de la durée d'existence de JavaScript, il comporte son lot de pièges et de pièges. Certains d’entre eux vont de légèrement amusants à aucun de mes codes ne fonctionne et je ne sais pas pourquoi.
Et, même si nous vivions à une époque où Internet Explorer 6 était à son apogée, il serait tout simplement trop tard pour essayer de corriger certaines de ces décisions de conception, car nous briserions trop le Web. Si tel était le cas à ce moment-là, imaginez si nous essayions aujourd'hui ! ??
Alors, pourquoi JavaScript ne fonctionne-t-il pas comme on pourrait s'y attendre ? Jetons un coup d'oeil.
L’exemple listé au début est accepté par les interpréteurs JavaScript mais ne donne pas le résultat attendu. La raison est due à l’injection automatique de point-virgule.
Certains langages, comme C#, sont dogmatiques quant à la fin de chaque ligne par un point-virgule. JavaScript utilise également des points-virgules pour indiquer la fin d'une ligne, mais le point-virgule est en réalité facultatif. Par facultatif, cela signifie que JavaScript appliquera un ensemble de règles complexes pour déterminer si un point-virgule aurait dû y figurer ou non.
Dans l'exemple du début, comme le crochet d'ouverture n'apparaît pas sur la même ligne que le retour, ASI en insère un pour nous. Ainsi, en ce qui concerne JavaScript, notre code ressemble en réalité à ceci :
function returnSomething() { return ; // <-- semicolon inserted by ASI, remainder of function not evaluated. { name: 'JavaScript Expert' contactMethod: 'Shine batsign at sky' } }
Le moyen d'éviter cela est d'avoir le support d'ouverture sur la même ligne qu'un retour. Et, même si les points-virgules sont techniquement facultatifs en JavaScript, cela va vous nuire à long terme de travailler avec ce concept.
Si vous avez une interview et que vous devez écrire du JS et que vous l'écrivez sans points-virgules en vous basant sur le raisonnement « mais ils sont facultatifs », il y aura beaucoup de brassage de papier et de rires. Ne le fais pas.
Imaginons que nous ayons un tableau simple :
function returnSomething() { return { name: 'JavaScript Expert' contactMethod: 'Shine batsign at sky' } }
Nous savons que nous pouvons afficher, pousser, ajouter et faire ce que nous voulons avec les tableaux. Mais nous savons aussi que JavaScript, comme d’autres langages, nous permet d’accéder aux éléments d’un tableau par index.
Cependant, ce qui est inhabituel avec JavaScript, c'est que vous pouvez également définir des éléments par index de tableau lorsque le tableau n'atteint même pas encore cet index :
function returnSomething() { return ; // <-- semicolon inserted by ASI, remainder of function not evaluated. { name: 'JavaScript Expert' contactMethod: 'Shine batsign at sky' } }
J'ai cependant une bonne question à vous poser : quelle est la longueur d'un tableau lorsque vous n'avez défini que trois éléments ? Peut-être de manière non intuitive, c'est 101. D'une part, il est raisonnable que les éléments du tableau 2 à 99 ne soient pas définis, mais d'autre part, nous ne définissons que trois objets, pas 100.
Pourquoi est-ce important ?
Peut-être que vos yeux sortent de votre tête et que vous dites : « D'accord Lewis, vous attribuez manuellement des éléments dans un tableau et regardez les roues se détacher ; ça te fait bizarre, pas JavaScript ».
Je comprendrais cette position. Mais imaginez un instant que vous faites quelque chose dans une boucle for imbriquée et que vous choisissez le mauvais itérateur ou que vous effectuez un calcul superposé.
À un moment donné, le processus de réflexion du type « Pourquoi est-ce que j'obtiens le résultat attendu, le résultat attendu, l'indéfini, le résultat attendu » va se transformer en folie, et bientôt en larmes ! Vous ne saviez pas que votre tableau s'agrandissait comme par magie pour s'adapter à ce que vous essayiez de faire.
Le seul problème était que vous essayiez de faire la mauvaise chose.
Pour comparer avec un autre langage comme C# (sans raison particulière), les tableaux sont de longueur fixe. Lorsque vous créez un tableau, vous devez définir une longueur. Même pour d'autres objets de collection dynamique, comme List Les exceptions ne sont pas agréables, mais c'est probablement la bonne chose à faire. Je veux dire, aviez-vous autrement l'intention de créer une gamme de fromages suisses ? Est-ce que quelqu'un a l'intention de faire ça ? Espérons que non. Ce ne sont que des gammes de fromages suisses si les développeurs sont suisses. Sinon, c'est juste une mauvaise programmation étincelante. Nous savons qu'en JavaScript nous pouvons attribuer de nouvelles fonctions aux prototypes. Ainsi, nous pouvons donner des chaînes ou des tableaux ✨des pouvoirs spéciaux✨. Bien sûr, cela est une pratique terrible car cela signifie que notre prototype de chaîne se comportera différemment des autres, ce qui provoque déjà un chagrin indicible pour de nombreux développeurs. Donc, on peut faire ceci par exemple : Et puis nous pouvons créer un objet chaîne : Et cela retournerait faux. C'est mignon, nous pouvons toujours intégrer au hasard nos fonctions dans l'implémentation définie en usine de la façon dont une chaîne peut agir. Bien sûr, toutes ces bonnes personnes se sont cassé le dos et ont passé des dizaines de milliers d'heures à définir JavaScript dans la spécification TC39, mais ne laissez pas cela vous dissuader d'utiliser vos fonctions aléatoires comme bon vous semble. Si nous ne sommes pas satisfaits de cette forme particulière de douleur, nous pouvons également attribuer aléatoirement de nouvelles fonctions à des objets complexes comme nous le souhaitons, garantissant que notre code sera une forme très particulière d'absurdités, comprise uniquement par vous-même et par Dieu. : Cependant, la bonne volonté s'épuise avec les objets primitifs, de façon surprenante : Pourquoi est-ce important ? Dans d'autres langages fortement typés, nous devons définir le type de données que nous stockons avant de pouvoir les stocker. JavaScript n'a pas ce même type de limitation, et il éloignera volontiers les objets de leur type défini pour essayer de les amener à bien jouer ensemble. D'une part, cela nous évite de convertir les variables en va-et-vient vers leurs types respectifs. Alors c'est pratique : Pourquoi est-ce important ? Dans les langages que nous utilisons aujourd'hui, un aspect important est ce qu'on appelle le « levage de fonctions ». Essentiellement, cela signifie que vous pouvez écrire vos fonctions dans votre fichier où vous le souhaitez, et vous pourrez les appeler avant que les fonctions ne soient déclarées : C'est pratique car nous n'avons pas besoin de réorganiser manuellement notre code pour le faire fonctionner. Mais il existe plusieurs façons de décrire une fonction. Dans cet exemple, nous avons utilisé une déclaration de fonction pour ce faire. On peut également utiliser une expression de fonction : Pourquoi est-ce important ? Dans d'autres langages, les propriétés des objets peuvent être attribuées ou elles peuvent être nulles. null indique que la propriété n'est pas attribuée. C’est simple à assimiler dans nos têtes : soit il y a un objet là, soit il est nul. Nous pouvons également réattribuer des propriétés à null si nous le souhaitons. JavaScript complique ce paysage en ayant null et également indéfini. Mais c'est pareil, non ? Soit vous avez un ballon en main, soit vous ne l’avez pas. Sans surprise, ce n’est pas du tout pareil. En JavaScript, null indique l'absence intentionnelle d'une valeur, tandis que undefined indique l'absence implicite d'une valeur. Donc, que ce soit intentionnel, explicite ou écrit dans le ciel, le fait est qu’aucune valeur = aucune valeur, n’est-ce pas ? Encore une fois, malheureusement, ce n’est pas ainsi que l’équation fonctionne. Eh bien, quel est le type d'indéfini ? D'accord, et quel est le type de null ? ? c'est un objet. Ainsi, en JavaScript, le type d'un objet complexe et null sont les mêmes — ils sont tous deux des objets : Pourquoi est-ce important ? L’immense popularité de JavaScript en tant que langage ne fait aucun doute aujourd’hui. À mesure que le temps passe et que d'autres écosystèmes tels que npm continuent d'héberger un grand nombre de packages, JavaScript ne fera que gagner en popularité. Mais ce qui est fait est fait. Peu importe à quel point il est étrange que null soit un objet ou que JavaScript insère des points-virgules là où bon lui semble, ces systèmes ne seront probablement jamais obsolètes, modifiés ou supprimés. Pour l’anecdote, je dirais que si l’injection automatique de point-virgule était désactivée du jour au lendemain, cela provoquerait probablement une panne mondiale plus importante que ne le ferait la mise à jour CrowdStrike. Certes, changer l’un d’entre eux ferait des ravages sur le web. Il est en fait plus sûr, et probablement plus pratique, de sensibiliser les développeurs à ces bizarreries linguistiques particulières plutôt que de revenir en arrière et de résoudre les problèmes d'origine. Alors allez faire les bons choix, et n'oubliez pas d'utiliser les points-virgules ! Le débogage du code est toujours une tâche fastidieuse. Mais plus vous comprenez vos erreurs, plus il est facile de les corriger. LogRocket vous permet de comprendre ces erreurs de manière nouvelle et unique. Notre solution de surveillance front-end suit l'engagement des utilisateurs avec vos frontends JavaScript pour vous donner la possibilité de voir exactement ce que l'utilisateur a fait qui a conduit à une erreur. LogRocket enregistre les journaux de la console, les temps de chargement des pages, les traces de pile, les requêtes/réponses réseau lentes avec les corps d'en-tête, les métadonnées du navigateur et les journaux personnalisés. Comprendre l'impact de votre code JavaScript n'aura jamais été aussi simple ! Essayez-le gratuitement. Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!
L'ajout de propriétés aux primitives est ignoré
function returnSomething()
{
return
{
name: 'JavaScript Expert'
contactMethod: 'Shine batsign at sky'
}
}
function returnSomething()
{
return ; // <-- semicolon inserted by ASI, remainder of function not evaluated.
{
name: 'JavaScript Expert'
contactMethod: 'Shine batsign at sky'
}
}
Composer ainsi nos objets est naturellement une idée terrible, mais comme nous nous engageons dans cette trahison, JavaScript nous oblige dans notre demande. Notre testObject prend en charge la nouvelle fonction que nous lui avons ajoutée.
L'interpréteur reconnaît notre tentative d'attribuer une fonction dans la chaîne primative. Cela nous fait même écho à la fonction. Mais ensuite, lorsque nous essayons de l'appeler, nous obtenons une TypeError : testString.onlyFalse n'est pas une fonction. Si ce n'est pas possible de faire cela, vous vous attendez généralement à ce que cela se produise lors de l'affectation, et non lors de l'appel de fonction.
Pour le meilleur ou pour le pire, JavaScript est un langage très flexible et dynamique. Cette flexibilité nous permet de composer des fonctionnalités qui ne sont pas possibles dans d’autres langages. Si quelque chose ne fonctionne pas, il faut s’attendre à une exception. JavaScript prenant cette commande maladroite et se disant « euh, d'accord », puis l'oubliant change cette attente fondamentale.
Tapez la coercition
C'est même pareil pour les booléens :
Cette approche est tout à fait saine et valable jusqu’à ce que nous souhaitions nous impliquer dans le rituel tabou connu sous le nom d’« addition ». Lorsque nous essayons d’additionner « 1 » et 1, que se passe-t-il ? Dans quelle direction se déroule la coercition de type ?
L'hilarité de la folie se multiplie quand on amène des bools à la fête :
Oh, est-ce parce qu'un booléen est en quelque sorte un nombre sous le capot ?
Non. C'est un booléen. JavaScript rase les bords embêtants du carré pour l'insérer dans ce trou rond pour des raisons.
Lorsque vous faites quelque chose d'aussi basique que d'additionner des nombres, le fait que les résultats varient peut créer des bugs étranges. C'est un bon rappel de s'en tenir au triple égal (===) lors des comparaisons, car zapper entre les types peut ne pas vous donner le résultat escompté.
Fonction de levage
function returnSomething()
{
return
{
name: 'JavaScript Expert'
contactMethod: 'Shine batsign at sky'
}
}
function returnSomething()
{
return ; // <-- semicolon inserted by ASI, remainder of function not evaluated.
{
name: 'JavaScript Expert'
contactMethod: 'Shine batsign at sky'
}
}
Il n'y a pas une énorme différence entre déclarer des fonctions dans les deux cas, mais si vous choisissez la mauvaise, vous ne pourrez pas appeler votre fonction à moins que vous ne l'appeliez après l'avoir déclarée.
Null est un objet
JavaScript ne dispose pas d’un système de vérification de type robuste intégré, et il n’existe qu’une poignée de types primitifs parmi lesquels choisir. Ainsi, utiliser typeof pour comprendre le contenu de notre variable peut devenir délicat. Si notre variable contient un objet valide, alors nous obtiendrons un objet. Mais si c’est nul, nous obtiendrons toujours un objet. Il est contre-intuitif de penser qu’une référence nulle est un objet.
Conclusion
LogRocket : déboguez plus facilement les erreurs JavaScript en comprenant le contexte