Casting a value to a String can be achieved by invoking the String constructor as a regular function (that is, not as a constructor):
String(456); // => "456"
String(true); // => "true"
String(null); // => "null"
String(NaN); // => NaN
String([1, 2, 3]); // => "1,2,3"
String({ foo: 1 }); // => "[object Object]"
String(function(){ return 'wow' }); // => "function(){ return 'wow' }"
Calling String() with your value is the most explicit and clear way of casting to a String, although there are more succinct patterns that are sometimes used:
'' + 1234; // => "1234"
`${1234}`; // => "1234"
These two expressions may appear equivalent, and for many values, they are. But, internally, they work differently. As we'll see later, the + operator will discern whether a given operand is a String by calling its internal ToPrimitive mechanism in such a way that the operand's valueOf (if it has one) will be queried before its toString implementation. However, when using template literals (such as `${value}`), any interpolated values will be converted directly to strings (without going via ToPrimitive). There is always the possibility that a value's valueOf and toString methods will provide different values. Take a look at the following example, which shows how we can manipulate the return values of the two seemingly equivalent expressions by defining our own toString and valueOf implementations:
const myFavoriteNumber = {
name: 'Forty Two',
number: 42,
valueOf() { return number; },
toString() { return name; }
};
`${myFavoriteNumber}`; // => "Forty Two"
'' + myFavoriteNumber; // => 42
This would be a rare situation to encounter but is still worth thinking about. Often, we presume that we can reliably cast any value to a string quite easily, but that may not always be the case.
Traditionally, it's quite common to rely on a value's toString() method and call it directly:
(123).toString(); // => 123
However, if the value is null or undefined, then you'll receive a TypeError:
null.toString(); // ! TypeError: Cannot read property 'toString' of null
undefined.toString(); // ! TypeError: Cannot read property 'toString' of undefined
Additionally, the toString method is not guaranteed to return string. Observe here how we can implement our own toString method that returns Array:
({
toString() { return ['not', 'a', 'string'] }
}).toString(); // => ["not", "a", "string"]
Therefore, it is always advisable to cast to a string via the very explicit and clear String(...). Using indirect forms of coercion, side effects, or blindly relying on toString can create unexpected results. Remember that even if you have a good knowledge of these mechanisms and feel comfortable using them, it doesn't mean other programmers will.