127 votes

valueOf () vs. toString () en Javascript

En Javascript, chaque objet a une valueOf() et la méthode toString (). J'aurais pensé que la méthode toString() a obtenu invoqué chaque fois qu'une chaîne de conversion est nécessaire, mais apparemment, il est éclipsé par valueOf().

Par exemple, le code

var x = {toString: function() {return "foo"; },
         valueOf: function() {return 42; }};
window.console.log ("x="+x);
window.console.log ("x="+x.toString());

imprime

x=42
x=foo

Ce qui me frappe comme en arrière .. si x est un nombre complexe, par exemple, je voudrais valueOf() pour me donner son ampleur (de sorte que le zéro deviendrait spécial), mais à chaque fois que j'ai voulu convertir une chaîne que je ne veux quelque chose comme "a+bi". Et je ne voudrais pas avoir à appeler toString() explicitement dans des contextes qui implique une chaîne de caractères.

Est-ce juste la façon dont il est?

111voto

user187291 Points 28951

La raison pour laquelle ("x="+x) donne "x=valeur" et non pas "x=tostring" est le suivant. Lors de l'évaluation des "+", javascript collecte d'abord les valeurs primitives des opérandes, puis décide si l'ajout ou la concaténation doit être appliqué, en se basant sur le type de chaque primitive.

Donc, c'est comment vous pensez que cela fonctionne

a + b:
    pa = ToPrimitive(a)
    if(pa is string)
       return concat(pa, ToString(b))
    else
       return add(pa, ToNumber(b))

et c'est ce qui se passe réellement

a + b:
    pa = ToPrimitive(a)
    pb = ToPrimitive(b)*
    if(pa is string || pb is string)
       return concat(ToString(pa), ToString(pb))
    else
       return add(ToNumber(pa), ToNumber(pb))

C'est, toString est appliquée au résultat de valueOf, de ne pas l'original de votre objet.

Pour de plus amples informations, consultez http://www.mozilla.org/js/language/E262-3.pdf $11.6.1


*Lorsqu'il est appelé dans le contexte de chaîne, ToPrimitive fait appeler toString, mais ce n'est pas le cas ici, parce que " + " ne pas appliquer tout type de contexte.

85voto

bcherry Points 3541

Voici un peu plus en détail, avant d'en arriver à la réponse:

var x = {
    toString: function () { return "foo"; },
    valueOf: function () { return 42; }
};

alert(x); // foo
"x=" + x; // "x=42"
x + "=x"; // "42=x"
x + "1"; // 421
x + 1; // 43
["x=", x].join(""); // "x=foo"

L' toString fonction n'est pas "emporté" par valueOf en général. Le standard ECMAScript en fait des réponses à cette question assez bien. Chaque objet a un [[DefaultValue]] de la propriété, qui est calculé sur la demande. Lors de la demande de cette propriété, l'interprète fournit également un "hint" pour ce genre de valeur qu'il attend. Si le soupçon est - String, alors toString il est utilisé avant l' valueOf. Mais, si le soupçon est - Number, alors valueOf sera utilisé en premier. Notez que si un seul est présent ou s'il renvoie à un non-primitif, il sera généralement appel de l'autre que le deuxième choix.

L' + de l'opérateur fournit toujours le soupçon Number, même si le premier opérande est une valeur de chaîne. Même si elle demande x pour son Number représentation, depuis le premier opérande retourne une chaîne de caractères à partir d' [[DefaultValue]], il ne concaténation de chaîne.

Si vous voulez vous assurer que toString est appelé pour la concaténation de chaîne, utilisez un tableau et l' .join("") méthode.

(ActionScript 3.0 modifie légèrement le comportement de l' +, cependant. Si l'un des deux opérandes est un String, il va le traiter comme un opérateur de concaténation de chaîne et utilisez l'indicateur String lorsqu'il appelle [[DefaultValue]]. Donc, en AS3, cet exemple rendements "foo, x=foo, foo=x, toto1, 43, x=foo".)

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