Javascript tiene muchos “trucos” en torno a los tipos y las conversiones de tipos, por lo que me pregunto si estos 2 métodos son iguales o si hay algún caso de esquina que los haga diferentes.
Christian C. Salvadó
No son completamente iguales y, de hecho, el constructor String llamado como una función (su primer ejemplo), al final, llamará al toString
método del objeto pasado, por ejemplo:
var o = { toString: function () { return "foo"; } };
String(o); // "foo"
Por otro lado, si un identificador se refiere a null
o undefined
no puedes usar el toString
método, le dará una TypeError
excepción:
var value = null;
String(null); // "null"
value.toString(); // TypeError
los String
constructor llamado como una función sería más o menos equivalente a:
value + '';
Las reglas de conversión de tipo de Objeto-a-Primitivo se describen detalladamente en la especificación, el [[DefaultValue]]
operación interna.
Resumido brevemente, al convertir de Objeto-a-Cuerdase siguen los siguientes pasos:
- Si está disponible, ejecute el
toString
método.- Si el
result
es un primitivodevolverresult
de lo contrario vaya al Paso 2.
- Si el
- Si está disponible, ejecute el
valueOf
método.- Si el
result
es un primitivodevolverresult
de lo contrario vaya al Paso 3.
- Si el
- Lanzar
TypeError
.
Dadas las reglas anteriores, podemos hacer un ejemplo de la semántica involucrada:
var o = {
toString: function () { return "foo"; },
valueOf: function () { return "bar"; }
};
String(o); // "foo"
// Make the toString method unavailable:
o.toString = null;
String(o); // "bar"
// Also make the valueOf method unavailable:
o.valueOf = null;
try {
String(o);
} catch (e) {
alert(e); // TypeError
}
Si quieres saber más sobre este mecanismo te recomiendo mirar el ToPrimitive
y el ToString
operaciones internas.
También recomiendo leer este artículo:
-
Hay una tercera “vía”, si llamas a esta:
new String(value)
en cualquier valor, siempre devolverá un objeto de cadena.– Herbusz
31 de diciembre de 2016 a las 20:31
-
@herbertusz
new String({toString: null})
lanza unTypeError
.– Константин Ван
10 de julio de 2019 a las 6:59
-
Con la adición de Símbolos
String()
y+ ''
ahora tienen una diferencia bastante significativa.String(Symbol())
correrá, peroSymbol() + ''
arrojará un error (y Symbol() pasará una guardia falsa, a diferencia de nulo e indefinido, por lo quex && (x + '')
ahora puede lanzar).– yerk
6 de agosto de 2019 a las 14:51
-
Parece que null no tiene los métodos toString y valueOf, pero String(null) devuelve ‘null’ sin arrojar un error. ¿Comportamiento especial?
– szhuravel
4 de noviembre de 2021 a las 14:29
jonathan
value.toString()
provocará un error si value
es nulo o indefinido. String(value)
no debe.
Por ejemplo:
var value = null;
alert(value.toString());
fallará porque value == null
.
var value = null;
alert(String(value));
debería mostrar un mensaje que dice “nulo” (o similar), pero no fallará.
-
Nunca he visto una excepción de puntero nulo en javascript… ¿dónde viste eso?
– Dagg Nabbit
15/10/2010 a las 18:59
-
bonito. sería aún mejor con un ejemplo
– mijal
15 de octubre de 2010 a las 19:03
-
@no, @casablanca Arreglado. Estoy acostumbrado a Java. @mykhal ¿Cómo se ve eso?
– Jonathan
15 de octubre de 2010 a las 19:07
-
Devuelve una cadena “null” 🙂
– moefinley
12 mayo 2015 a las 16:28
Nabbit Dagg
String(value)
debe tener el mismo resultado que value.toString()
en todos los casos, excepto para valores sin propiedades como null
o undefined
. ''+value
producirá el mismo resultado.
Cuerda() [the constructor call] básicamente está llamando a la .Encadenar()
.Encadenar() y Cuerda() se puede llamar en valores primitivos (número, booleano, cadena) y básicamente no hará nada especial:
verdadero => ‘verdadero’
falso => ’falso’
17 => ’17’
‘hola’ => ‘hola’
Pero llamar a estas funciones en objetos es donde las cosas se ponen interesantes:
si el objeto tiene su propia función .toString(), se llamará cuando necesite que este objeto se trate como una cadena (explícita/implícitamente)
let obj = {
myName:"some object",
toString:function(){ return this.myName; }
}
//implicitly treating this obj as a string
"hello " + obj; //"hello some object"
//OR (explicitly)
"hello " + String(obj) //calling the existent toString function
//OR
"hello " + obj.toString(); //calling toString directly
Por cierto, si desea tratar este objeto como un número, debe tener un .valor de() función definida en él.
¿Qué pasa si tenemos ambos en un objeto?
si queremos tratar este objeto como una cadena => use .Encadenar()
si queremos tratar este objeto como un número => use .valor de()
¿Qué pasa si solo tenemos .valor de() definido?
.valor de() definido dentro del objeto se llamará si queremos manejar el objeto como una cadena o como un número
Burakhan Aksoy
Acabo de probar esto con ES6 y descubrí que para String()
para mirar valueOf()
dentro del objeto, el objeto tiene que tener toString()
método. Si el objeto no tiene toString()
luego vuelve la consola '[object Object]'
independientemente de tener valueOf()
O no. Así que en el primer “paso”, siempre tenemos que tener toString()
independientemente, de lo contrario String()
el método no miraría valueOf
.
Por favor, chequee esto:
let obj = {
name:'b',
age:22,
valueOf: function(){
return 'heeee';
}
}
String(obj); // prints '[object Object]'
Por otra parte,
let obj = {
name:'b',
age:22,
toString:null,
valueOf: function(){
return 'heeee';
}
}
String(obj); // prints 'heeee'
let obj = {
name: 'b',
age: 22,
valueOf: function() {
return 'heeee';
}
}
console.log(String(obj));
let obj2 = {
name: 'b',
age: 22,
toString: null,
valueOf: function() {
return 'heeee';
}
}
console.log(String(obj2));