The String valueOf() method
By Flavio Copes
Learn how the JavaScript valueOf() method returns the primitive string value of a String object, working exactly like the toString() method does.
valueOf() returns the primitive string value wrapped inside a String object:
const str = new String('Test')
str.valueOf() //'Test'
It works exactly like toString() on strings.
Why do we need it?
JavaScript has two kinds of strings.
String primitives are what you create with quotes. String objects are what you get from new String(). They look similar, but they are different things:
typeof 'Test' //'string'
typeof new String('Test') //'object'
You’ll almost always work with primitives. But if you ever end up with a String object, valueOf() unwraps it and gives you the primitive back.
Comparing String objects
Comparison is where the difference bites:
const wrapped = new String('Test')
wrapped === 'Test' //false
wrapped.valueOf() === 'Test' //true
=== does not coerce. On one side you have an object, on the other a primitive, so the comparison is false even though the text is the same.
JavaScript calls valueOf() for you in some operations. Concatenation, for example:
const wrapped = new String('Te')
wrapped + 'st' //'Test'
What happens with an empty String object?
Objects are always truthy, even when they wrap an empty string:
const empty = new String('')
if (empty) console.log('this runs')
if (empty.valueOf()) console.log('this does not')
The empty string primitive '' is falsy, but the object wrapping it is not. If your code checks a string for emptiness with if, a String object slips right through. Call valueOf() first, or check str.length instead.
You can also call valueOf() on a primitive directly:
'Test'.valueOf() //'Test'
JavaScript temporarily wraps the primitive in a String object to run the method, then returns the primitive. You get back what you started with.
My advice: never create strings with new String(). There’s no good reason to. But knowing valueOf() exists helps when a library, or old code, hands you one of these wrapper objects and your comparisons start failing.
Related posts about js: