|Written by Mike James|
|Friday, 08 March 2013|
Page 1 of 2
A newer version of this article can be found at:
For example, wouldn't it be nice if you could create an object that could take part in arithmetic expressions in a natural way?
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.
Following this you can write:
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:
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:
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:
then you can write things like
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?
This is very flexible, but you should always return a value that is appropriate for the meaning of the object you are working with.
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:
Now what do you think displays if you try:
The answer is the string "ten" because alert expects a string argument.
Now what do you think you get if you write:
The answer is 11 because the addition requires a numeric value.
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:
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.
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.
|Last Updated ( Thursday, 23 May 2019 )|