Comme nous le savons tous, == en JavaScript est une opération relativement complexe. Ses règles de fonctionnement sont très étranges et peuvent facilement faire des erreurs, ce qui en fait l'une des "pires caractéristiques" en JavaScript.
Sur la base de la lecture soigneusement de la spécification ECMAScript, j'ai dessiné une image. J'ai pensé qu'après avoir compris cette image, vous comprendrez à fond tout sur l'opération ==. En même temps, j'ai essayé de prouver à tout le monde à travers cet article que == n'est pas une mauvaise chose. Il est facile à maîtriser et semble même raisonnable et pas si mal.
Tout d'abord, l'image:
== La description exacte des règles d'opération est ici: l'algorithme de comparaison d'égalité abstrait. Cependant, avec une description si compliquée, êtes-vous sûr de ne pas vous sentir étourdi après l'avoir lu? Pouvez-vous l'utiliser pour guider votre pratique immédiatement?
Cela ne fonctionne certainement pas. Après tout, la spécification concerne les développeurs de l'environnement de course JavaScript (par rapport aux développeurs de moteurs V8), pas pour les utilisateurs de langues. L'image ci-dessus traduit les spécifications en un formulaire qui est pratique pour tout le monde.
Avant d'introduire chaque partie de la figure 1 en détail, passons en revue les connaissances sur les types dans JS:
Il existe deux types de valeurs dans JS: Type de base et type d'objet.
Les types de base incluent: Undefined, Null, Boolean, Number et String.
Le type non défini et le type nul n'ont qu'une seule valeur, à savoir indéfini et nul; Le type booléen a deux valeurs: vrai et faux; Il existe de nombreuses valeurs du type de nombre; et le type de chaîne a d'innombrables valeurs (théoriquement).
Tous les objets ont des méthodes de valeur de () et toString (), qui sont hérités de l'objet et peuvent bien sûr être réécrites par des sous-classes.
Considérez maintenant l'expression:
x == y
où x et y sont des valeurs de l'un des six types.
Lorsque les types de x et y sont les mêmes, x == y peut être converti en x === y, et ce dernier est très simple (la seule chose à noter est NAN), donc ci-dessous, nous considérons uniquement les cas où les types de x et y sont différents.
1. Avoir et aucun
Dans la figure 1, six types de valeurs JavaScript sont représentés par des rectangles à fond bleu. Ils sont d'abord divisés en deux groupes:
Chaîne, numéro, booléen et objet (correspondant à la grande boîte rectangulaire à gauche)
Non défini et nul (correspondant à la boîte rectangulaire à droite)
Quelle est la base du regroupement? Jetons un coup d'œil. Undefined et nul à droite sont utilisés pour indiquer l'incertitude, non ou vide, tandis que les quatre types à droite sont tous déterminés, existants et non vides. Nous pouvons dire ceci:
À gauche est un monde d'existence et à droite est un monde vide.
Par conséquent, il est raisonnable de comparer toute valeur dans les deux mondes avec faux. (c'est-à-dire que la ligne horizontale reliant deux rectangles sur la figure 1 est marqué faux)
2. Vide et vide
Undefined et nul en JavaScript sont un autre endroit qui nous écrase souvent. Il est généralement considéré comme un défaut de conception, dans lequel nous ne creuserons pas. Mais j'ai entendu dire que l'auteur de JavaScript le pensait initialement:
Si vous prévoyez d'attribuer une variable à la valeur du type d'objet, mais que vous n'avez pas encore attribué de valeur, vous pouvez utiliser Null pour représenter l'état pour le moment (l'une des preuves est que le résultat du type de null est «objet»); Au contraire, si vous prévoyez d'attribuer une variable à la valeur du type d'origine, mais que vous n'avez pas encore attribué de valeur, vous pouvez utiliser non défini pour représenter l'état pour le moment.
Peu importe que cette rumeur soit crédible ou non, il est raisonnable que le résultat de la comparaison entre les deux soit vrai. (c'est-à-dire vrai marqué sur la ligne verticale à droite sur la figure 1)
Avant de passer à l'étape suivante, parlons des deux symboles de la figure 1: les lettres majuscules N et P. Ces deux symboles ne signifient pas positifs et négatifs dans la section PN. Plutôt:
N représente l'opération de tonUmber, ce qui signifie convertit l'opérande en nombre. Il s'agit d'une opération abstraite dans la spécification ES, mais nous pouvons utiliser la fonction Number () dans JS pour la remplacer de manière équivalente.
P représente l'opération toprimitive, c'est-à-dire convertissant l'opérande en valeur du type d'origine. Il s'agit également d'une opération abstraite dans la spécification ES, et il peut également être traduit en code JS équivalent. Mais c'est un peu plus compliqué. Pour le dire simplement, pour un objet obj:
Toprimitive (OBJ) équivaut à: Calculez d'abord obj.valueof (), si le résultat est la valeur d'origine, ce résultat est renvoyé; Sinon, obj.toString () est calculé, et si le résultat est la valeur d'origine, ce résultat est renvoyé; Sinon, une exception est lancée.
Remarque: Il y a une exception ici, c'est-à-dire un objet de date de type, qui appellera d'abord la méthode toString ().
Dans la figure 1, une ligne marquée N ou P indique que lorsque les deux types de données, il est connecté pour effectuer l'opération ==, l'opérande sur le côté marqué N ou P doit d'abord effectuer le tonUmber ou la transformation toprimitive.
3. Vrai et faux
Comme le montre la figure 1, lorsqu'une valeur booléenne est comparée à d'autres types de valeurs, la valeur booléenne est convertie en un nombre. Spécifiquement
vrai -> 1
Faux -> 0
Cela ne nécessite pas du tout trop d'abus verbal. Pensez-y, en C, il n'y a pas du tout de type booléen. Les entiers 1 et 0 sont généralement utilisés pour représenter la logique vraie ou fausse.
Iv. Séquence de caractères
Dans la figure 1, nous divisons la chaîne et le nombre en groupe. Pourquoi? Parmi les six types, la chaîne et le nombre figurent des séquences de caractères (du moins littéralement). Une chaîne est une séquence de tous les caractères juridiques, tandis qu'un nombre peut être considéré comme une séquence de caractères qui remplissent certaines conditions. Par conséquent, les nombres peuvent être considérés comme un sous-ensemble de chaînes.
Selon la figure 1, lors de l'exécution du fonctionnement == des chaînes et des nombres, vous devez utiliser l'opération Tonumber pour convertir la chaîne en nombres. En supposant que x est une chaîne et y est un nombre, alors:
x == y -> nombre (x) == y
Alors, quelle est la règle pour convertir les chaînes en chiffres? La spécification est décrite de manière très compliquée, mais d'une manière générale, il s'agit de supprimer les citations des deux côtés de la chaîne et de voir si elle peut former un numéro juridique. Si c'est le cas, le résultat de la conversion est ce nombre; Sinon, le résultat est nan. Par exemple:
Numéro ('123') // Résultat 123
Numéro ('1.2e3') // Résultat 1200
Numéro ('123abc') // résultat nan
Bien sûr, il y a des exceptions, comme le résultat de la conversion d'une chaîne vide en un nombre est 0. En ce moment
Numéro ('') // Résultat 0
V. simple et complexe
Les types primitifs sont des types simples, ils sont simples et faciles à comprendre. Cependant, l'inconvénient est que la capacité d'expression est limitée et difficile à développer, il y a donc des objets. Un objet est une collection d'attributs, et l'attribut lui-même peut être un objet. Par conséquent, les objets peuvent être construits arbitrairement suffisamment complexes pour représenter diverses choses.
Mais parfois, les choses sont compliquées et pas une bonne chose. Par exemple, tout le monde n'a pas le temps, la patience ou la nécessité de le lire du début à la fin. Habituellement, il suffit de ne comprendre que ses pensées centrales. Le document a donc des mots clés et des aperçus. Il en va de même pour les objets dans JavaScript. Nous devons avoir un moyen de comprendre ses principales caractéristiques, de sorte que les objets ont des méthodes ToString () et ValueF ().
La méthode toString () est utilisée pour obtenir une description de texte de l'objet; et la méthode de valeur de () est utilisée pour obtenir la valeur propre de l'objet.
Bien sûr, c'est juste ma propre compréhension. De plus, comme son nom l'indique, la méthode toString () a tendance à renvoyer une chaîne. Qu'en est-il de la méthode de valeur de ()? Selon la description de la spécification, il a tendance à renvoyer un nombre - bien que dans le type intégré, la méthode de valeur de () ne renvoie que le numéro et la date.
Selon la figure 1, lorsqu'un objet est comparé à un non-objet, l'objet doit être converti en type primitif (bien que lorsque vous comparez avec un type booléen, le type booléen doit être converti en un type numérique en premier, mais le type d'objet doit être converti en un type primitif suivant). C'est également raisonnable. Après tout, == n'est pas une comparaison strictement égale. Nous avons seulement besoin de retirer les principales caractéristiques de l'objet pour participer à l'opération et de mettre les caractéristiques secondaires de côté.
Six. Tout est compté
Regardons en arrière sur la figure 1. Les lignes marquées n ou p à l'intérieur n'ont pas de direction. Si nous marquons les flèches sur ces lignes, les points de connexion de la fin marqués n ou P à l'autre extrémité, alors nous obtiendrons (sans considérer les indéfinis et nuls):
Avez-vous découvert quelque chose? Oui, pendant le processus de calcul, tous les types de valeurs ont tendance à se convertir en types numériques. Après tout, une célébrité a dit un jour:
Tout est compté.
7. Donnez-moi juste une châtaigne
Il y a trop de non-sens dans le passé, alors voici un exemple pour prouver que la figure 1 est en effet pratique et efficace pour guider la pratique.
Exemple, calculez ce qui suit:
[''] == faux
Tout d'abord, les deux opérandes sont respectivement de type objet et de type booléen. Selon la figure 1, il est nécessaire de convertir le type booléen en un type numérique, et le résultat de la conversion de faux en numérique est 0, donc l'expression devient:
[''] == 0
Les deux opérandes deviennent le type d'objet et le type numérique. Selon la figure 1, le type d'objet doit être converti en type d'origine:
Tout d'abord, appelez [] .valueof (). Étant donné que la méthode de valeur de () du tableau renvoie elle-même, le résultat n'est pas le type d'origine. Continuez à appeler [] .toString ().
Pour les tableaux, l'algorithme de la méthode toString () consiste à convertir chaque élément en type de chaîne, puis à le concaténer à son tour avec '', ', donc le résultat final est une chaîne vide, qui est une valeur du type d'origine.
À ce stade, l'expression devient:
'' == 0
Les deux opérandes deviennent des types de chaînes et des types numériques. Selon la figure 1, le type de chaîne doit être converti en types numériques. Comme mentionné précédemment, la chaîne vide devient un nombre de 0. Ainsi, l'expression devient:
0 == 0
Jusqu'à présent, les types de deux opérandes sont enfin les mêmes, et le résultat est évidemment vrai.
À partir de cet exemple, nous pouvons voir que pour maîtriser les règles de l'opération ==, en plus de nous souvenir de la figure 1, nous devons également nous rappeler les règles des méthodes ToString () et Value () de ces objets intégrés. Y compris l'objet, le tableau, la date, le numéro, la chaîne, le booléen, etc.
8. Résumons
La déclaration précédente est très déroutante. Ici, je résumerai les règles de l'opération == exprimées à la figure 1:
Le résultat de Undefined == null est vrai. Le résultat de leur comparaison avec toutes les autres valeurs est faux.
Lorsque un numéro de chaîne ==, la chaîne est convertie en un nombre.
Valeur booléenne == Lorsque d'autres types sont utilisés, la valeur booléenne est convertie en nombre.
Lorsqu'un objet == numérique / chaîne, l'objet est converti en type primitif.
Enfin, j'ai changé l'image pour être pour le divertissement uniquement :)
Ok, c'est fini. Si vous pensez que cet article vous est utile, veuillez l'aimer afin que plus de gens puissent le voir.
De plus, veuillez souligner les erreurs dans l'article.