toString()
is not guaranteed to return a string because it is, after all, just a method. Try to guess what is printed to the console when the following JavaScript is executed:var obj = {Because
nine: 9,
toString: function() {
return this.nine;
},
valueOf: function() {
return 10;
}
};
console.log(obj.toString() === '9');
console.log('' + obj === '9');
console.log('' + obj.toString() === '9');
console.log(obj + obj);
console.log(String(obj) === '9');
obj.toString()
returns a number, not a string, obj.toString()
is the number 9
, not the string '9'
, so the first expression is false
.In the second example, I would expect that because
''
is a string, the value on the right of the +
would also be coerced to a string via its toString()
method, which means the result would be '9'
. But I am wrong! It turns out that valueOf
takes precedence, so '' + obj
evaluates to '10'
, which means '' + obj === '9'
is false
. It would be true
if there were no valueOf
method defined on obj
, though.Because
toString()
is called explicitly in the third example, '' + obj.toString()
becomes '' + 9
, which evaluates to '9'
, so the expression is true
.The fourth one is interesting because
'99'
, 18
, and 20
are all reasonable guesses, but it turns out that valueOf()
takes precedence again, so this evaluates to 20
. If there were no valueOf()
method defined on obj
, then the result would be 18
.In the final example,
String()
is used as a function (and not as a constructor function, which you should never do!), and it does, in fact, return a string, so String(obj) === '9'
evaluates to true
. I always assumed that the implementation of String
was something like:function(s) {Though a few years back, I discovered that
return '' + s.toString();
};
alert.toString()
throws an exception on IE6 (also alert.toString
evaluates to undefined
on IE6), but '' + alert
and String(alert)
return 'function alert() { [native code] }'
, as expected. At least in that case, my proposed implementation for String()
would not work, though IE6 has been known to be nonstandard and buggy...
What will really mess with your head later is the undocumented parameter of valueOf (at least in Firefox).
ReplyDeleteTry the following:
f=function(s){alert(s)}
0+{valueOf:f} //'undefined'
+{valueOf:f} //'number'
String({toString:null,valueOf:f}) //'string'
Object({valueOf:f}) //'object'
x=/./,x.valueOf=f,x(x) //'function'
Interesting blog post. Enjoyed reading it.
ReplyDelete