<p>Like most object-oriented programming languages, JavaScript provides built-in ways to convert between objects and primitive values, by way of the special <code>toString</code> and <code>valueOf</code> methods. This article will cover the basics of these methods, but then dive into the details of how this stuff really works, bad stuff, performance, and browser support.</p>
<h3 id='types_and_primitives'>Types and Primitives</h3>
<p>To understand this article, you’ll need to understand the difference between <strong>primitive and non-primitive values</strong> in JavaScript. There are 5 primitive types, which are associated with the various primitive values.</p>
<ul>
<li><strong>Null</strong>: The value <code>null</code>.</li>
<li><strong>Undefined</strong>: The value <code>undefined</code>.</li>
<li><strong>Number</strong>: All numbers, such as <code>0</code> and <code>3.14</code>. Also <code>NaN</code>, and <code>Infinity</code>.</li>
<li><strong>Boolean</strong>: The values <code>true</code> and <code>false</code>.</li>
<li><strong>String</strong>: All strings, such as <code>"foo"</code> and <code>""</code>.</li>
</ul>
<p>All other values are non-primitive, including arrays, functions, and plain old objects. For completeness, here are the results of the <code>typeof</code> operator, applied to these values:</p>
<pre><code>typeof null; // "object"
typeof undefined; // "undefined"
typeof 0; // "number" (`typeof NaN` is also "number")
typeof true; // "boolean"
typeof "foo"; // "string"
typeof {}; // "object"
typeof function () {}; // "function"
typeof []; // "object"</code></pre>
<span class='note'>__Note__: `typeof null` should _not_ be `"object"`. This is a mistake from the first versions of JavaScript, but it's really too late to fix. A more sensible type would have been `"null"`, but this is what we're stuck with.</span>
<p>If you’ve got that down, then we’re ready to move on to the basics of <code>toString</code> and <code>valueOf</code>. If you’re already familiar with the basics, feel free to skip ahead to “How it Works”.</p>
<h2 id='basic_usage'>Basic Usage</h2>
<p>We’ll be using a simple example <code>population</code> object that holds a country name and a population. Lets code that up.</p>
<pre><code>function population(country, pop) {
return {
country: country,
pop: pop
};
}
var america_pop = population("USA", 350e6);
var mexico_pop = population("Mexico", 200e6);
var canada_pop = population("Canada", 200e6);
alert(america_pop); // [object Object]
var north_america_pop = america_pop + mexico_pop + canada_pop;
alert(north_america_pop); // [object Object][object Object][object Object]</code></pre>
<p>This works, but the calls to <code>alert</code> are not very useful. What we’d really like is for the first <code>alert</code> to show <code>'[Population "USA" 350000000]'</code> and the second to show <code>"750000000"</code>. So, let’s code that up next.</p>
<h3 id='tostring'>toString</h3>
<p>All objects inherit the method <code>toString</code> from <code>Object.prototype</code>, which returns <code>"[object Object]"</code>. However, we can easily override this by providing <code>toString</code> as a method of our object, or its prototype. In this example, we’ll attach it directly to each instance, but feel free to use the prototype instead.</p>
<pre><code>function population(country, pop) {
return {
country: country,
pop: pop,
toString: function () {
return "[Population " +
"\"" + country + "\" " +
pop +
"]";
}
}
}
var america_pop = population("USA", 350e6);
alert(america_pop); // [Population "USA" 350000000]</code></pre>
<span class='note'>__Note__: I'm using __closure__ on the `country` parameter, rather than using `this.country`. This only works due to how the constructor is set up. If you placed `toString` on the prototype, you would need to use `this.country`.</span>
<h3 id='valueof'>valueOf</h3>
<p>All JavaScript objects also inherit the method <code>valueOf</code> from <code>Object.prototype</code>. By default, this method simply returns the object itself, but is generally overridden to convert an object to a <code>Number</code>, or another primitive value, so it can be used by operators like <code>+</code>. We can do the same thing as above to complete our basic example.</p>
<pre><code>function population(country, pop) {
return {
country: country,
pop: pop,
toString: function () {
return "[Population " +
"\"" + country + "\" " +
pop +
"]";
},
valueOf: function () {
return pop;
}
};
}
var america_pop = population("USA", 350e6);
var mexico_pop = population("Mexico", 200e6);
var canada_pop = population("Canada", 200e6);
alert(america_pop); // [Population "USA" 350000000
var north_america_pop = america_pop + mexico_pop + canada_pop;
alert(north_america_pop); // 750000000</code></pre>
<p>Here we’ve defined the <code>valueOf</code> function of our <code>population</code> object to return the population, which should be a <code>Number</code>.</p>
<h2 id='how_it_works'>How It Works</h2>
<p>As with most things in JavaScript, the process by which <code>toString</code> gets called is not as simple as you’d think. Let’s explore what happens when <code>alert(america_pop)</code> is called.</p>
<ol>
<li><code>alert</code> calls <code>GetValue</code> on the reference. This returns the object it points at.</li>
<li><code>alert</code> calls <code>ToString</code> on the value (this is <em>not</em> the same as the object’s <code>toString</code>)</li>
<li><code>ToString</code> calls <code>ToPrimitive</code> on the value, passing the <em>hint</em> <code>String</code>.</li>
<li><code>ToPrimitive</code> calls the object’s internal <code>[[DefaultValue]]</code> method with the <em>hint</em> <code>String</code>.</li>
<li><code>[[DefaultValue]]</code> calls the <code>toString</code> property of the object, with the object as <code>this</code>.</li>
<li>The result of <code>toString</code> is a primitive value, so it is returned, all the way up the chain to the <code>ToString</code> method.</li>
<li>Since the result is of type <code>String</code>, <code>ToString</code> returns all the way to <code>alert</code>.</li>
<li><code>alert</code> displays the value.</li>
</ol>
<p>While this is a lot, it’s pretty straightforward. However, he key mechanism that needs more explaining is the <code>ToPrimitive</code> function. This function is used to take an arbitrary value and get a corresponding primitive value instead. If the input is already a primitive value then the value will be returned without conversion. However, if the value is non-primitive, then it will call the internal <code>[[DefaultValue]]</code> method to find a <strong>default value</strong> for the object.</p>
<p><code>[[DefaultValue]]</code> is an internal property of every object. It’s a method that takes an optional <em>hint</em>, which should be either <code>Number</code> or <code>String</code>. If a <em>hint</em> is not provided, it will default to <code>Number</code> unless the object is a <code>Date</code>, in which case it defaults to <code>String</code> (this is silly). After this has been figured out, it will call <code>toString</code> and <code>valueOf</code>, in order, to find a primitive value. This is where the <em>hint</em> comes into play. If the <em>hint</em> is <code>Number</code>, then <code>valueOf</code> will be tried first, but if it’s <code>String</code> then <code>toString</code> will be tried first. Here’s the ensuing process:</p>
<ol>
<li>If the first method exists, and is callable, call it and get the result, otherwise skip to 3.</li>
<li>If the result of 1 is a primitive, return it.</li>
<li>If the second method exists, and is callable, call it and get the result, otherwise skip to 5.</li>
<li>If the result of 3 is a primitive, return it.</li>
<li>Throw a <code>TypeError</code> exception.</li>
</ol>
<p>The value that is returned by <code>[[DefaultValue]]</code> is guaranteed to be primitive. If it was not, a <code>TypeError</code> would have been thrown. This also implies that <code>toString</code> and <code>valueOf</code> should return primitives on order to be useful in this context.</p>
<h3 id='confusion_about_the__operator'>Confusion About the + Operator</h3>
<p>Here’s an example with a (possibly) unexpected result:</p>
<pre><code>var foo = {
toString: function () {
return "foo";
},
valueOf: function () {
return 5;
}
};
alert(foo + "bar"); // 5bar
alert([foo, "bar"].join("")); // foobar</code></pre>
<p>In this context, we’re using the <code>+</code> operator to do string concatenation. But, <code>foo</code> was <em>not</em> converted to a string using <code>toString</code>, it was turned into a number using <code>valueOf</code>, then used for string concatenation. This probably isn’t what we want, but it is how it works. It’s a side-effect of the overloading of the <code>+</code> operator for arithmetic and string concatenation. The <code>+</code>operator has a well-defined process:</p>
<ol>
<li>Evaluate the left-hand side, and get the value.</li>
<li>Evaluate the right-hand side, and get the value.</li>
<li>Call <code>ToPrimitive</code> on both the left-hand and right-hand sides (without a <em>hint</em>)</li>
<li>If either primitive value is a <code>String</code>, then skip to 7.</li>
<li>Call <code>ToNumber</code> on both values.</li>
<li>Return the sum of the values.</li>
<li>Call <code>ToString</code> on both values.</li>
<li>Return the concatenation of both values.</li>
</ol>
<p>Since no <em>hint</em> is passed to the <code>ToPrimitive</code> calls, the <em>hint</em> will be defaulted to <code>Number</code> (unless it’s a <code>Date</code>, which defaults to <code>String</code>). This means that our <code>valueOf</code> function will be called, instead of <code>toString</code>. It’s not until <em>after</em> the primitive values are retrieved that the interpreter decides whether it is going to do string concatenation or arithmetic. That’s why our example above returns <code>"5bar"</code> instead of <code>"foobar"</code>.</p>
<h3 id='bad_stuff'>Bad Stuff</h3>
<p>There is one really bad feature of all this, which is that <code>ToPrimitive</code> does not enforce any type-checking on the return values, other than that they are primitive. This means you can write code like this:</p>
<pre><code>var foo = {
toString: function () {
return 5;
},
valueOf: function () {
return "foo";
}
};
alert(foo.toString() + 1); // 6 (bad!)
alert(foo + 1); // "foo1" (no good!)
alert(+foo); // NaN (the worst!)</code></pre>
<p>The <code>valueOf</code> method can be forgiven for not type-checking, because it is more generic. You’d expect it to be able to return any suitable primitive value. However, the <code>toString</code> method has <em>no such excuse</em>. This is simply a bad feature. You can, of course, mitigate by using <code>String(foo)</code> instead of <code>foo.toString()</code>, which will call <code>toString</code> and then convert that result to a string. But you should not have to do this, or worry about this. Please do not make objects with <code>toString</code> methods that do not return strings.</p>
<h2 id='how_about_performance'>How About Performance?</h2>
<p>After understanding the complexity that goes into these implicit conversion, I got curious about how that affects performance. So I decided to test the time it takes to perform an <code>[].join(obj)</code> over 1,000,000 iterations in the major browsers. I did one test with the object being implicitly cast to a string, and one where I called the <code>toString</code> method manually (i.e. <code>[].join(obj.toString())</code>). As expected, the explicit call was faster in most cases.</p>
<ul>
<li><strong>Firefox 3.6.2</strong>: 874ms vs. 320ms - <strong>almost 3x faster</strong>.</li>
<li><strong>Chrome 5</strong>: 94ms vs. 47ms - <strong>2x faster</strong>.</li>
<li><strong>Opera 10.50</strong>: 155ms vs 182ms - <strong>a little slower</strong>.</li>
<li><strong>Safari 4</strong>: 409ms vs 280ms - <strong>almost 2x faster</strong>.</li>
<li><strong>Internet Explorer 8</strong>: 2856ms vs 2786ms - <strong>about the same</strong>.</li>
<li><strong>Internet Explorer 9</strong> (preview): 645ms vs 633ms - <strong>about the same</strong>.</li>
</ul>
<span class='note'>___Note 1___: The Firefox, Chrome, Opera, and Safari tests were all run on a Macbook Pro running OS X 10.5. The IE tests were run on a desktop running Windows 7. [Run the tests yourself here.](http://www.bcherry.net/playground/defaultvalues)</span><span class='note'>___Note 2___: I chose to use the `[].join` method because doing so was most likely to avoid any dead-code elimination optimizations in modern browsers. I've had trouble with this before, in Firefox. I _did_ try testing with the `String()` constructor, with similar results in most browsers. Opera was an exception where using the explicit `toString` was close to __5x faster__. In Firefox, the explicit cast was a bit faster, but both cases were about 100x faster than the `[].join` method (and other browsers), which means the code-path was probably being removed by the dead code eliminator.</span>
<p>The takeaway from this performance test is that it’s always best to call your object’s type-conversion methods directly, rather than relying on the interpreter to do the complex series of method calls and comparisons needed to do it automatically. The Opera 10.50 result is very strange, but it’s not particularly slower, so I wouldn’t worry about it. The gains made in other browsers more than make up for the outlier Opera result.</p>
<h2 id='how_about_browser_support'>How About Browser Support?</h2>
<p>Like many things in the ECMAScript specification, these processes are complex, and I doubted that all browsers would implement them exactly as specified. So, in that <a href='http://www.bcherry.net/playground/defaultvalues'>test suite from earlier</a>, I added compliance checks. I was quite surprised to see that all major browsers, including versions of Internet Explorer going back to at least IE 5.5, implement these mechanisms correctly. This is even the case with the awkward handling when developers do things like make <code>toString</code> return a number instead of a string. All browsers handle the code according to the specification. This is great news.</p>
<p>But the specification unhelpfully introduced ambiguity in one particular area: the absence of a <em>hint</em> for the <code>ToPrimitive</code> function. Here’s the exact wording:</p>
<blockquote>
<p>All native ECMAScript objects except Date objects handle the absence of a hint as if the hint Number were given; Date objects handle the absence of a hint as if the hint String were given. Host objects may handle the absence of a hint in some other manner.</p>
</blockquote>
<p>That the standard explicitly allows browsers to deviate here worried me. Included in that test suite was a check that, in the absence of a <em>hint</em>, <code>Date</code> objects will default to <code>String</code> and <code>Boolean</code> objects will default to <code>Number</code>. All browsers passed this check as well, which means that browser support for all of this functionality seems to be <strong>consistent</strong> and <strong>correct</strong>.</p>
<h2 id='conclusions'>Conclusions</h2>
<p>I hope this was useful in understanding how these mechanisms work in JavaScript. There are three important things to take away from this article:</p>
<ol>
<li>Implement <code>toString</code> and <code>valueOf</code> on your commonly-reused objects. They can help you write clearer, more concise code, and make debugging easier too.</li>
<li>All browsers implement object-to-primitive conversion according to the specification, so you can safely consult it for more detail.</li>
<li>When performance is important, always try to call your type-conversion methods directly, instead of relying on JavaScript’s implicit calls.</li>
</ol>
<p>You can find the <a href='http://www.bcherry.net/playground/defaultvalues'>test suite used for this article here</a> if you’re interested in trying to replicate my results. Please let me know if you find contradictory results to what I posted here.</p>
<p>Thanks for reading! If you have questions or feedback then leave a comment below or contact me directly.</p>