Tout au long de cette série d'articles, nous avons parlé de la coercition de types, de ses différences et de ses performances dans des langages à typage dynamique..
Si vous venez de rejoindre la série, consultez les articles précédents pour vous assurer que vous êtes au courant de l'état actuel des choses:
Alors que l'autre article portait sur les langages faiblement typés et les types de données à un niveau élevé, nous allons examiner quelques exemples spécifiques de coercition de types dans un langage faiblement typé, ainsi que les pièges que nous pouvons rencontrer sans savoir comment fonctionne la coercition et comment il peut se retourner.
Plus précisément, nous allons examiner plusieurs exemples en utilisant JavaScript. Bien que les résultats obtenus, ils ne traduiront pas nécessairement le 1: 1 dans d’autres langues, mais ils fourniront quand même une série de tests que vous pourrez utiliser. peut jouer dans tout ce que vous utilisez dans vos projets quotidiens ou secondaires et évaluer les résultats que vous voyez.
On peut soutenir que l'un des problèmes les plus courants dans les langages faiblement typés survient chaque fois que nous faisons des comparaisons. Bien sûr, il y a d'autres fois où s'attendre à ce qu'une variable soit un type alors que c'est vraiment un autre peut nous affecter négativement, mais les problèmes les plus courants se produisent lorsque nous effectuons un type de comparaison..
Ces comparaisons peuvent prendre la forme d'opérations d'égalité, d'opérations conditionnelles, d'opérations au niveau du bit ou commutateur / boîtier
opérations.
Comme mentionné dans les articles précédents de cette série, différentes langues utilisent différentes méthodes pour contraindre les types de données. Les exemples que nous examinons dans cet article peuvent donc légèrement différer dans le travail que vous effectuez..
C'est-à-dire que nous allons examiner ces exemples en utilisant JavaScript car il s'agit d'un langage très répandu, mais les règles sont toujours applicables dans d'autres langages - c'est simplement que d'autres langages peuvent accorder une priorité différente à un type de données, les résultats de la contrainte peuvent être un peu différents.
Cela dit, voyons comment JavaScript gère les comparaisons entre les types de données à l'aide de l'opérateur d'égalité (==
), l'opérateur d'égalité stricte (===
) et lorsque vous utilisez des valeurs telles que indéfini
et nul
.
Avant d’examiner les comparaisons entre différents types de données, prenons un moment pour noter que, en JavaScript, indéfini
et nul
sont deux types de valeurs différentes. Comme si cela ne suffisait pas, la comparaison des deux valeurs peut devenir encore plus confuse.
Tout d'abord, notez ce qui suit:
typeof (indéfini)
dans la console, alors le résultat serait indéfini
.typeof (null)
dans la console, alors le résultat serait objet
.Ensuite, si vous déclariez une variable sans lui attribuer une valeur et évaluiez son type, vous verriez indéfini
.
/ ** * Déclare une variable 'nom' mais ne lui attribue pas de valeur. * Exécutez le résultat de 'typeof' sur une console et * vous recevrez * 'indéfini'. * / var nom; typeof (nom);
Ensuite, supposons que nous choisissions d’initialiser la variable avec un nul
valeur. Si vous deviez évaluer la variable en utilisant Type de
on vous donnerait un objet
résultat.
// D'abord, nous allons déclarer la variable var number; / ** * À ce stade, si nous évaluions la variable * à l'aide de typeof, nous aurions un "indéfini". * / // Attribuez maintenant à la variable une valeur de 'null' number = null; / ** * Et évalue la variable. À ce stade, nous allons * nous retourner la valeur de 'objet'. * / typeof (nombre);
Déroutant? Rappel de plus tôt que cela en JavaScript, nul
est un objet
où indéfini est son propre type - indéfini
.
Cela dit, nous pouvons maintenant comprendre pourquoi les comparaisons peuvent devenir difficiles chaque fois que nous effectuons des comparaisons sur des valeurs sans connaître explicitement leur type..
Tout au long de cette section, nous allons examiner les résultats de la comparaison de valeurs de types différents, mais voir comment elles sont évaluées les unes par rapport aux autres en utilisant à la fois des comparaisons d’égalité et des comparaisons strictes d’égalité..
Notez que tous les exemples énumérés ci-dessous doivent pouvoir être exécutés dans la console d'un navigateur, telle que Firebug ou les outils de développement de Chrome..
Pour commencer, nous allons commencer par indéfini
et nul
.
// Renvoie true undefined == null; null == undefined; // renvoie false undefined === null; null === undefined;
Notez que dans le premier cas, l'opérateur d'égalité renvoie une valeur de la comparaison après effectuer une contrainte de type. C’est-à-dire que l’interprète fait de son mieux pour deviner ce que nous entendons par cette comparaison.
Dans le second cas, nous utilisons l'opérateur d'égalité stricte. Dans ce cas, aucune contrainte de type ne se produit. Au lieu de cela, il prend les valeurs exactement comme elles sont et les compare.
Examinons ensuite comment déclarer une variable, ne pas lui attribuer de valeur, puis exécuter une comparaison..
// Déclarez la variable, ne lui attribuez pas de valeur var exemple; // Par rapport à undefined, renvoie true dans les deux cas example == undefined; exemple === undefined // Par rapport à null, renvoie vrai ou faux exemple == null; // true exemple === null; // false // Assigne une valeur à la variable example = null; // Faisons maintenant un exemple de comparaison strict === null; // renvoie true
Comme vous pouvez le constater, les choses commencent à se compliquer un peu lorsque nous commençons à déclarer et à comparer des variables avec ou sans valeurs.
Une fois que nous commençons à introduire des chaînes, des nombres et des valeurs booléennes, cela peut devenir encore plus compliqué. Commençons par les chaînes et les nombres. Nous allons commencer par déclarer une variable avec une valeur de chaîne de 42
et un nombre avec le 42
et ensuite nous effectuerons nos comparaisons.
var sNumber, iNumber; sNumber = '42'; iNombre = 42; // Les comparaisons d'égalité donnent true sNumber == iNumber; // Une comparaison stricte donne fausse sNumber === iNumber;
De nouveau, notez que dans le premier cas, l’interprète tente de contraindre les valeurs des variables puis de les comparer. Dans le premier cas, cela fonctionne - nous comparons une valeur de chaîne de 42
à une valeur numérique de 42
, mais quand nous utilisons la comparaison d'égalité stricte et obtenons faux
.
Le second cas est techniquement plus précis car la première valeur est une chaîne et la seconde un nombre. La comparaison de deux valeurs de types différents doit toujours donner la valeur false.
Bien que nous ayons examiné cela dans un article précédent, qu'en est-il du cas des nombres et des booléens??
var iNumber, bBoolean; iNumber = 0; bBoolean = false; // Renvoie true iNumber == bBoolean; // Renvoie false iNumber === bBoolean; // Renvoie true iNumber = 1; bBoolean = true; iNumber == bBoolean; // Renvoie false iNumber === bBoolean;
À ce stade, vous devriez commencer à remarquer un modèle: chaque fois que vous comparez des valeurs de types différents, JavaScript peut correctement contraindre des valeurs, mais il donne le résultat le plus précis possible lorsque vous utilisez l'opérateur d'égalité stricte..
Enfin, regardons un exemple qui combine des chaînes, des nombres et des booléens.
var sExample, iExample, bExample; sExample = '1'; iExample = 1; bExample = true; // Renvoie true sExample == iExample; // Renvoie false sExample === iExample; // Renvoie true iExample == bExample; // Renvoie false iExample === bExample; // Renvoie true sExample == bExample; // Renvoie false sExample === bExample;
Notez que ce sont des comparaisons de base; cependant, lorsque cela est fait dans le contexte d’une sinon
ou si / sinon si / sinon
vous voyez comment cela peut perturber le flux de contrôle à travers le conditionnel.
Notez que lorsque vous effectuez des opérations logiques telles que &&
et ||
ainsi que des opérateurs au niveau des bits tels que Et
et |
que les règles de contrainte continuent à s'appliquer. Pour ce faire, vous voulez vous assurer que lorsque vous effectuez ces opérations, utilisez des valeurs exactement du même type pour obtenir les résultats les plus précis possible..
Autrement, la coercition peut entraîner un faux positif ou un faux négatif.
Ceci termine notre examen sommaire, débutant, des types de données et de la contrainte de type dans des langages à typage dynamique. En fin de compte, les règles empiriques sont de toujours utiliser des opérateurs d'égalité stricts et de s'assurer que les variables avec lesquelles vous travaillez sont du même type. Si vous n'êtes pas sûr, vous pouvez toujours les convertir explicitement en utilisant les stratégies décrites plus haut dans la série..
Tout au long de cette série, nous avons examiné la manière dont les types varient et se comportent des langages fortement typés aux langages faiblement typés. Nous avons examiné les différences entre la coercition et la coercition, ainsi que certains pièges potentiels pouvant entraîner une trop grande dépendance de l'interprète ou du compilateur lors de la comparaison..
Enfin, nous avons examiné quelques stratégies pour rédiger un code plus défensif en nous assurant que nous disposions du type de données dont nous avons besoin et comment utiliser des opérateurs de comparaison stricts pour nous assurer d'obtenir les résultats dont nous avons besoin..
Comme mentionné précédemment, nous avons utilisé JavaScript pour nos exemples dans cette liste d'articles, mais d'autres langages faiblement typés sont sujets aux mêmes pièges. La hiérarchisation des contraintes varie, mais les stratégies décrites dans cette série devraient vous aider à écrire un code plus résistant lorsque vous travaillez dans des langages faiblement typés..