¿Cuál es la diferencia entre String (value) vs value.toString ()

104

Javascript tiene muchos "trucos" en torno a los tipos y conversiones de tipos, así que me pregunto si estos 2 métodos son iguales o si hay algún caso de esquina que los haga diferentes.

AlfaTeK
fuente

Respuestas:

121

No son completamente iguales y, de hecho, el constructor String llamado como función (su primer ejemplo), al final, llamará al toStringmétodo del objeto pasado, por ejemplo:

var o = { toString: function () { return "foo"; } };
String(o); // "foo"

Por otro lado, si un identificador se refiere a nullo undefinedno puede usar el toStringmétodo, le dará una TypeErrorexcepción :

var value = null;
String(null);     // "null"
value.toString(); // TypeError

El Stringconstructor llamado como función sería aproximadamente equivalente a:

value + '';

Las reglas de conversión de tipo de objeto -a-- Primitive están detalladas descritas en la especificación, el [[DefaultValue]]funcionamiento interno.

Resumiendo brevemente, al convertir de Object -a-- cadena , se toman los pasos siguientes:

  1. Si está disponible, ejecute el toStringmétodo.
    • Si resultes una primitiva , regrese result; de lo contrario, vaya al Paso 2.
  2. Si está disponible, ejecute el valueOfmétodo.
    • Si resultes una primitiva , regrese result; de lo contrario, vaya al Paso 3.
  3. Tirar 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 desea saber más acerca de este mecanismo Yo recomiendo mirar el ToPrimitivey las ToStringoperaciones internas.

También recomiendo leer este artículo:

CMS
fuente
1
Hay una tercera "forma", si llama a esto: new String(value)en cualquier valor, siempre devolverá un objeto de cadena.
Herbertusz
@Herbertusz new String({toString: null})lanza un TypeError.
Константин Ван
Con la adición de Símbolos String()y + ''ahora tienen una diferencia bastante significativa. String(Symbol())se ejecutará, pero Symbol() + ''arrojará un error (y Symbol () pasará una guardia falsa, a diferencia de null e undefined, por x && (x + '')lo que ahora puede lanzar).
yeerk
24

value.toString()causará un error si valuees nulo. String(value)no debería.

Por ejemplo:

var value = null;
alert(value.toString());

fallará porque value == null.

var value = null;
alert(String(value));

debería mostrar un mensaje que diga "nulo" (o similar), pero no fallará.

Jonathan
fuente
3
Nunca he visto una excepción de puntero nulo en javascript ... ¿dónde lo viste?
Dagg Nabbit
bonito. sería aún mejor con un ejemplo
mykhal
@no, @casablanca Fijo. Estoy acostumbrado a Java. @mykhal ¿Cómo se ve eso?
Jonathan
Devuelve una cadena "nula" :)
moefinley
1

String(value)debería tener el mismo resultado que value.toString()en todos los casos, excepto para valores sin propiedades como nullo undefined. ''+valueproducirá el mismo resultado.

Dagg Nabbit
fuente
1

String () [la llamada al constructor ] básicamente está llamando al .toString ()

.toString () y String () se pueden llamar en valores primitivos (número, booleano, cadena) y básicamente no harán 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 (), será llamado siempre que necesite que este objeto sea tratado como una cadena (explícitamente / 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 una función .valueOf () definida en él.

¿Qué pasa si tenemos ambos en un objeto?

si queremos tratar este objeto como una cadena => use .toString ()

si queremos tratar este objeto como un número => use .valueOf ()

¿qué pasa si solo tenemos .valueOf () definido?

.valueOf () definido dentro del objeto se llamará si queremos manejar el objeto como una cadena o como un número

Louay Alosh
fuente