null
et undefined
n'ont pas de méthode toString
ou valueOf
. Afaik utilise String
appelle la méthode toString
de son paramètre (par exemple, String({})
=> [object Object]
).
Pourquoi String(null)
ou String(undefined
fonctionne-t-il alors? Cela ne fait pas implicitement Object.prototype.toString.call(null)
. parce que cela donne [object Null]
.
[edit]: d'après la spécification ECMA-262/5ème édition (page 48). Cela n’ajoute rien à la clarification, je dirais:
/*
Table 13 — ToString Conversions
-------------------------------------------------------------------------
Argument Type | Result
-------------------------------------------------------------------------
Undefined | "undefined"
Null | "null"
Boolean | If the argument is true, then the result is "true".
... | ...
*/
Après avoir examiné ma réponse précédente, il semble qu'une refonte complète de ma réponse précédente est nécessaire. J'avais beaucoup compliqué la situation, car la réponse courte est qu'il s'agit de cas spéciaux spécifiés par des normes.
La spécification pour String()
(String
utilisée en tant que fonction):
15.5.1.1 Chaîne ([valeur])
Renvoie une valeur String (et non un objet String) calculée par ToString (valeur). Si valeur n'est pas fournie, la chaîne Vide "" est renvoyée.
La fonction ToString
(qui existe en interne, pas en mode utilisateur) est définie comme suit (9.8):
"L'opération abstraite ToString convertit son argument en une valeur de type String conformément au tableau 13"
Argument Type | Result
Null | "null"
Undefined | "undefined"
Cela signifie que String(null)
et String(undefined)
vont dans cette table spéciale de types et renvoient simplement les valeurs de chaîne valorisées "null"
et "undefined"
.
Une pseudo-implémentation utilisateur-terrain ressemble à ceci:
function MyString(val) {
if (arguments.length === 0) {
return "";
} else if (typeof val === "undefined") {
return "undefined";
} else if (val === null) {
return "null";
} else if (typeof val === "boolean") {
return val ? "true" : "false";
} else if (typeof val === "number") {
// super complex rules
} else if (typeof val === "string") {
return val;
} else {
// return MyString(ToPrimitive(val, prefer string))
}
}
(Notez que cet exemple ignore le cas du constructeur (new MyString()
) et qu'il utilise des concepts utilisateur-terrain plutôt que moteur-terrain.)
Je me suis un peu laissé emporter et j'ai trouvé un exemple d'implémentation (la V8 étant spécifique):
string.js:
// Set the String function and constructor.
%SetCode($String, function(x) {
var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
if (%_IsConstructCall()) {
%_SetValueOf(this, value);
} else {
return value;
}
});
macros.py:
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg));
runtime.js:
function NonStringToString(x) {
if (IS_NUMBER(x)) return %_NumberToString(x);
if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
if (IS_UNDEFINED(x)) return 'undefined';
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
}
Le NonStringToString (qui est essentiellement ce qui présente un intérêt) est heureusement défini dans psuedo-JS-land. Comme vous pouvez le constater, il existe en effet un cas particulier pour null/true/false/undefined.
Il n’ya probablement que quelques vérifications et traitements supplémentaires dans des cas spéciaux tels que null
et undefined
.
MDN dit :
Il est possible d'utiliser String comme alternative "plus sûre" toString, car même si elle appelle toujours le toString sous-jacent, elle fonctionne également pour les valeurs null et indéfinie.
Vous voudrez peut-être voir le ES5 annoté (qui est beaucoup plus lisible que le PDF ECMAScript 5) qui indique que: new String([ value ])
http://es5.github.com/#x15 .5.2.1 appelle [ToString]
http://es5.github.com/#x9.8 (il existe un tableau des cas de conversion spéciaux) pour convertir la valeur qui lui est transmise en chaîne.
String(null)
crée un objet chaîne et lui transmet la valeur par défaut null.