JavaScript Objects With Value - valueOf and toString
Written by Mike James   
Friday, 08 March 2013
Article Index
JavaScript Objects With Value - valueOf and toString
Functions v Objects

JavaScript objects have a default value. In fact, they have two default values depending on the context. You can easily add default values of your choice to a custom object or even built-in objects.

A newer version of this article can be found at:

JavaScript Jems - Objects with Values

valueOf

All JavaScript objects will supply a value when asked for one. In many cases the value isn't of much use and hence it tends to be overlooked as a useful feature.

For example, wouldn't it be nice if you could create an object that could take part in arithmetic expressions in a natural way?

Something like:

var result=myObject*10;

In fact this is very easy to achieve. If you just define a new object then the arithmetic will return a NaN - Not a Number. To provide a return numeric value that can be used in an arithmetic expression you have to provide the object with a valueOf function property.

For example:

var myObject={
 valueOf:function(){
   return 20;
 }
};

Following this you can write:

var result=myObject*10;

and the result will be 200.

If an object has a valueOf function defined then it can be used to supply a value whenever the object is used in an expression and a numeric value is required.

What do you think you get if you write:

var result=myObject:

The answer is not that result is set to the simple value 20. This is an object assignment and result is set to another reference to myObject. This can be confusing because if you now try something like:

var a=result*10;

you will still see 200 stored in a because result refers to the same object as myObject and so valueOf is called to return 20 in the expression. In other words result behaves as if it was 20 in an expression just as myObject does. However, if anything changes myObject so that it returns some other value, then a will not equal 200 after the expression.

It also works if a Boolean value is required. For example, if you change the definition of myObject to:

var myObject={
  valueOf:function(){
    return true;
  }
};

then you can write things like

!myObject

which evaluates to false.

At this point you might be wondering how you can work out what to return from valueOf when you can't know how it will be used in an expression. For example, what if you you use the Boolean valued myObject in an arithmetic expression?

Of course, there is nothing to worry about because JavaScript's type juggling will sort it out for you and true will be converted to the value 1. In the same way returning a default value of 1 will be treated as true within a Boolean expression.

This is very flexible, but you should always return a value that is appropriate for the meaning of the object you are working with.

toString

You may not need a separate booleanValueOf type function but you do need a separate string value function. The reason is that what an object should return may be fundamentally different when a string value is required. For example, if a string value is required the object may need to format a numeric value so that it can be displayed.

The good news is that it is easy to set a separate default string value using the toString function. For example, let's add a toString function to the myObject object:

var myObject={
 valueOf:function(){
   return 10;
 },
 toString:function(){
  return "ten";
 }
};

Now what do you think displays if you try:

alert(myObject);

The answer is the string "ten" because alert expects a string argument.

Now what do you think you get if you write:

var result= myObject+1;

The answer is 11 because the addition requires a numeric value.

It shouldn't come as a surprise to learn that you don't have to return a string from toString. JavaScript has no way of enforcing a return type, so in practice if you return some other type of value it will be converted to a string before being used.

One of the most useful things that you can do with toString is to define something more useful than the default object:Object that you see when you use alert or the debugging console. You can define a toString function that provides some useful debug information, as in:

toString:function(){
 return "myObject Current State:"+10;
}

 

Prototype

You can supply a valueOf or a toString function to all of the instances of an object by defining them as part of the prototype object. You can even use this mechanism to override the valueOf and toString of built-in objects - but in general don't do it because other programmers might try to use your modified object without realizing that they are modified.

For example:

Object.prototype.toString = function() {
 return "My String ";};
alert({});

will display "My String" in place of the usual object:Object message. You can use this as a debugging trick to discover information about an object.

You can override toString and valueOf in other built-in objects such as Number and String but don't expect it to be of much use because often the conversions are performed without calling the functions for reasons of efficiency and speed.

 

Banner



Last Updated ( Thursday, 23 May 2019 )