38 votes

Comment est 1 == [1] en javascript?

Récemment, on m'a posé cette question dans une interview.

  var a = 1;
 var b = [1];
 

Qu'est-ce que a == b; retournera?

Lorsque j'ai vérifié cela sur ma console de navigateur Chrome, je l'ai compris.

 var a = 1;
var b = [1];
a == b;
true
 

J'ai aussi vérifié

 var a = 1;
var b =(1);
a == b;
true
 

Je sais que b dans un tableau de taille 1. Cela signifie-t-il que la taille du tableau est assignée à b. Je suis vraiment confus. Quelqu'un peut-il m'expliquer la logique?

52voto

Margaret Bloom Points 3177

Je n'ai pas vraiment compris à partir de Rayonne de répondre à la manière dont valueOf et toString entrent en jeu lors de la conversion d'un objet à une valeur primitive; alors j'ai creusé dans le ECMAScript 2015 cahier des charges.

Avertissement: Longue réponse.

Nous voulons vérifier l'expression 1 == [1].

À partir de la 12.10 Opérateurs d'Égalité , nous voyons que, après l'extraction des expressions de valeurs, la dernière étape est

  1. De retour à la suite de l'exécution de l'Abstrait Comparaison d'Égalité rval == lval

Résumé Comparaison d'Égalité est définie au chapitre 7.2.12 Abstrait Comparaison d'Égalité.

7.2.12 Abstrait Comparaison D'Égalité
La comparaison x == y, où x et y sont des valeurs, produit des vrai ou faux. Une telle comparaison est effectuée comme suit:

  1. ReturnIfAbrupt(x).
  2. ReturnIfAbrupt(y).
  3. Si le Type(x) est le même que le Type(y), alors
    un. Retourner le résultat de l'exécution Stricte Comparaison d'Égalité x === y.
  4. Si x est nul et y est pas défini, retourner la valeur true.
  5. Si x n'est pas définie et y est nul, retourne true.
  6. Si le Type(x) est le Nombre et le Type(y) est une Chaîne, retourner le résultat de la comparaison x == ToNumber(y).
  7. Si le Type(x) est une Chaîne et le Type(y) est le Nombre, de retourner le résultat de la comparaison ToNumber(x) == y.
  8. Si le Type(x) est de type Boolean, retourner le résultat de la comparaison ToNumber(x) == y.
  9. Si le Type(y) est un Booléen, retourner le résultat de la comparaison x == ToNumber(y).
  10. Si le Type(x) est une Chaîne, un Nombre ou un Symbole et le Type(y) est l'Objet, puis retourner le résultat de la comparaison x == ToPrimitive(y).
  11. Si le Type(x) est l'Objet et le Type(y) est une Chaîne, un Nombre ou un Symbole, puis retourner le résultat de la comparaison ToPrimitive(x) == y.
  12. Retourne la valeur false.

L'expression 1 == [1] relève de cas 10.
Donc, fondamentalement, comme prévu, le tableau [1] est convertie en une valeur de type primitif.

ToPrimitive est de définir au 7.1.1 ToPrimitive ( input [, PreferredType] )

Le résumé de l'opération ToPrimitive prend un argument d'entrée et un argument optionnel PreferredType. L' résumé de l'opération ToPrimitive convertit son argument d'entrée à un non-type d'Objet.

Je n'ai pas compris la citation complète depuis le seul intéressant, pour cet exemple, les pièces sont:

  1. Le PreferredType argument (en fait un indicateur de var) est converti à partir de "par défaut" (puisqu'il n'est pas passé) à "nombre".
  2. OrdinaryToPrimitive est appelée avec les mêmes arguments.

E maintenant la partie intéressante, OrdinaryToPrimitive effectuer les opérations suivantes:

  1. Affirmer: Type(O) est l'Objet
  2. Affirmer: Type(indice) est une Chaîne de caractère et sa valeur est "chaîne" ou "nombre".
  3. Si le soupçon est la "chaîne", puis
    un. Laissez methodNames être «"toString", "valueOf"».
  4. Autre chose,
    un. Laissez methodNames être «"valueOf", "toString"».
  5. Pour chaque nom dans methodNames dans l'ordre de la Liste, n'
    un. Laissez la méthode Get(O, nom).
    b. ReturnIfAbrupt(méthode).
    c. Si IsCallable(méthode) est vrai, alors
    ... j'. Laissez résultat(Appel de méthode, O).
    ... ii. ReturnIfAbrupt(le résultat).
    ... iii. **Si le Type(résultat) n'est pas Objet, résultat de retour. **
  6. Jeter une exception TypeError

Afin de convertir [1] valeur primitive, le moteur d'exécution tout d'abord essayer de l'appeler valueOf. Cette méthode retourne un tableau lui-même, qui est un objet par 5.c.iii la méthode toString est ensuite appelée.
Cette méthode retourne les éléments de la matrice comme une liste séparée par des virgules, donc elle retourne la chaîne de caractères "1".

Nous sommes donc réduits en comparant 1 == "1" qui, de par les règles de l' Abstrait Comparaison d'Égalité, point 6, les moyens de convertir "1" en nombre 1 et que d'effectuer la comparaison triviale 1 = 1.

Le triste lecteur est invité à vérifier comment l'Égalité Stricte Comparaison est en fait défini dans la norme.


Vous pouvez jouer avec cette conversions pour mieux comprendre, voici un exemple d'aire de jeux fichier HTML

<html>
    <head><title>title</title></head>
    <body>
        <script>
            var old_valueOf = Array.prototype.valueOf;
            var old_toString = Array.prototype.toString;

            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return old_valueOf.apply(this); };
            Array.prototype.toString = function(){ console.log("Array::toString"); return old_toString.apply(this); };

            console.log(1 == [1]); //Array::valueOf, Array::toString, true 

            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return 2; };

            console.log(1 == [1]); //Array::valueOf, false 

            Array.prototype.valueOf = function(){ console.log("Array::valueOf"); return {}; };
            Array.prototype.toString = function(){ console.log("Array::toString"); return {} };

            console.log(1 == [1]); //Array::valueOf, Array::toString, Uncaught TypeError: Cannot convert object to primitive value
        </script>
    </body>
</html>

51voto

Rayon Points 29869

Si un objet est en rapport avec un nombre ou une chaîne, JavaScript tente de retourner la valeur par défaut de l'objet. Les opérateurs tentent de convertir l'objet en valeur primitive, une String ou Number de la valeur, à l'aide de l' valueOf et toString méthodes des objets. Si cette tentative de convertir l'objet échoue, une erreur d'exécution est générée.[Ref]

var a = 1;
var b = [1];
//What is happening when `(a==b)`
//typeof a;   ==> number
//typeof b;  ==>object
//Object is converted to Primitive using `valueOf` and `toString` methods of the objects
var val = b.valueOf().toString();
console.log('Values after conversion is: ' + val + '  And typeof converted value is:  ' + typeof val);
//typeof val; ==> string
//a == b; will be evaluated as `true` because `'1' == 1` hence..
console.log(a == b); //'1'==1 ==> true

Comme valeur convertie est de type String, Lorsque l'on compare un number et string, l' string est convertie en number de la valeur et puis comparaison stricte est appliquée.

13voto

gdgr Points 932

Cela est dû au type de comparaison.

En javascript, on peut utiliser == ou === pour la comparaison. Dans le cas d'un triple égal à égal, c'est ce qu'on appelle l'égalité sans contrainte de type, en d'autres termes, c'est une comparaison stricte.

D'égalité avec la contrainte de type

À l'inverse, cela signifie que l'utilisation de la double est égal à l'opérande est à égalité avec le type de contrainte.

Qu'est-ce que cela signifie?

Tout simplement, cela signifie que javascript utiliser en haut de méthodes afin de convertir la valeur d'un type primitif, prêt pour la comparaison. Plus précisément, ces méthodes sont .valueOf() et .toString().

Voici quelques exemples:

0 == false   // true, auto type coercion
0 === false  // false, because they are of a different type
1 == "1"     // true, auto type coercion
1 === "1"    // false, because they are of a different type

Ergo:

1 == [1] // true
1 === [1] // false, because they are of a different type

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X