Note: the comment on the right side is the return value of the left side statement.
String('foo') // foo
JSON.stringify('foo') // "foo"
'foo'.toString() // foo
String({}) // [object Object]
JSON.stringify({}) // {}
{}.toString() // [object Object]
String(null) // null
JSON.stringify(null) // null
null.toString() // Cannot read property 'toString' of null
String(undefined) // undefined
JSON.stringify(undefined) // undefined
undefined.toString() // Cannot read property 'toString' of undefined
null
and undefined
are not object. Ok null
is but it should not be. Nevertheless both lack a toString
method, hence the: Cannot read property 'toString'
.
const obj = {
baz: 'baz',
toString: function () { return 'foo'; },
valueOf: function () { return 'bar'; }
};
String(obj) // foo
JSON.stringify(obj) // {"baz:"baz}
obj.toString() // foo
obj + 'qux' // barqux
const arr = [obj, 'qux'];
arr[0] + arr[1] // fooqux
String
function calls the toString
method behind the scene.+
operator the concatenation uses the valueOf
method.[obj, 'qux']
is calling the toString
method.obj.toString = null;
String(obj) // bar
JSON.stringify(obj) // {"baz:"baz,"toString":null}
obj.toString() // obj.toString is not a function
The toString
method is not available so the String
function falls back to the valueOf
method.
obj.valueOf = null;
String(obj) // Cannot convert object to primitive value
JSON.stringify(obj) // {"baz:"baz,"toString":null,"valueOf":null}
obj.toString() // obj.toString is not a function
None of the needed methods are here, it throws.
const obj = {
baz: 'baz',
toString: function () { return 'foo'; },
valueOf: function () { return 'bar'; }
};
obj.valueOf = null;
obj + 'qux' // fooqux
const arr = [obj, 'qux'];
arr[0] + arr[1] // fooqux
Funny enough, or not, the concatenation with the +
operator uses toString
as a fallback if valueOf
is not available.
It's the exact opposite behavior as with the string conversion by the String
function.
Source: http://www.adequatelygood.com/Object-to-Primitive-Conversions-in-JavaScript.html