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

4 minutos de lectura

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.

avatar de usuario
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 undefinedno 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:

  1. Si está disponible, ejecute el toString método.
    • Si el result es un primitivodevolver resultde lo contrario vaya al Paso 2.
  2. Si está disponible, ejecute el valueOf método.
    • Si el result es un primitivodevolver resultde lo contrario vaya al Paso 3.
  3. 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 un TypeError.

    – Константин Ван

    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á, pero Symbol() + '' arrojará un error (y Symbol() pasará una guardia falsa, a diferencia de nulo e indefinido, por lo que x && (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

avatar de usuario
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

avatar de usuario
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

avatar de usuario
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));

¿Ha sido útil esta solución?