Just JavaScript - The Object Expression
Written by Ian Elliot   
Monday, 25 June 2018
Article Index
Just JavaScript - The Object Expression
Every Object Has a String Value
Type Conversion?

Expression Quiz

To make sure you have all of this worked out, see if you can answer the following questions:

1. What is 

     1 + 2 + "3" + 4 + 5

2. What is

     1 + "2" * 3

3. What is

     "4" + 1 + "2" * 3

4. What is the final value of a

     a="1";
  
  a = a + 2 + 2;

5. What is the final value of a  

     a = "1";
     a += 2 + 2;

Try to work them out without typing in the code, then see if you are right by running the code.

Even if you are right, see below for the full explanations.

Answers

  1. "3345" 
    Reason: All the + operators have the same priority and are hence evaluated from left to right. The first operator is 1+2 and so the answer is Number 3. The second operator is now 3+"3" and as one of the operands is a String the first 3 is converted to a String and the result is "33". The third operator is now "33"+4 and by the same reasoning this is concatenation and the result is "334". The final operator is "334"+4 and again this is concatenation and the result is "3344". 

  2. 7
    Reason: * has a higher priority than + so the first operator is "2"*3 and after "2".valueOf() the result is 6. The second operator is now 1+6 so the result is Number 7.

  3. "416"
    Reason: * has the higher priority so the first operator is "2"*3 and after "2".valueOf() the result is 6. But now the + operators have equal priority and the expression to evaluate is "4"+1+6. The first operator is "4"+1 which evaluates to "41". The final operator is "41"+6 which evaluates to "416".

  4. "122"
    Reason: The first operation is concatenation and hence so is the second.

  5. "14"
    Reason: Despite this looking like the previous example, the expression on the right is evaluated first and then the a+ operation is performed. That is, it is equivalent to a=a+(2+2); or "1"+4.

Every Object Has a String Value

Just as the valueOf method gives every object a value, the toString method does the same sort of thing for strings.

  • Every object has a toString method that can be used to supply a String representation of the object. 

  • You can define your own toString method or you can accept the use of the default. 

  • You can provide a toString method to a custom object as in the case of the valueOf method.  

For example:

var myObject={}; 
myObject.valueOf=function(){return 1;}; 
myObject.toString=function(){return "myString";};

Now we have a custom object which has a value and a String representation. 

As in the case of valueOf, you don't have to return a String object as the result of a toString method, but not to do so would be misleading in the extreme. 

So when is toString used in an expression?

There are two ways that toString can be invoked during the evaluation of an expression. 

The first is to get a primitive value for the object. 

Put simply, if the expression evaluator fails to get a primitive object from valueOf it will try toString to get one. 

That is, it first uses the valueOf method. If this returns a primitive value then it stops. If this returns a general object the evaluator next tries the toString method to see if this can provide a primitive value. If this works the value is used in the expression; if it doesn't then you get a runtime error:

Cannot convert object to primitive value

To see this in action try:

var myObject1={};
myObject1.valueOf=function(){return {};}; myObject1.toString=function(){return {};}; a=1+myObject1;

Notice that in this case both methods return an empty object, which isn't a primitive value. 

Notice that toString can return a Number object and this will work:

myObject1.valueOf=function(){return {};}; myObject1.toString=function(){return 1;};
a=1+myObject1;

This doesn't throw a runtime error and it results in 2 stored in a. 

The evaluator doesn't care about what type of primitive object it gets from valueOf or toString – as long as it is a primitive object.

The second way the toString method can be called is if the primitive value obtained earlier is the wrong sort of primitive. 

For example, consider concatenation. You might think that if one of the operands in the expression was a String:

a=myObject1+"1";

then the toString method would be called to convert the other object to a String. 

This isn't what happens.

What happens is the same two steps – first valueOf is called and if it doesn't provide a primitive value toString is called. 

At this point we assume we have a primitive value, pv, ready to be used in the expression. 

If the expression turns out to be concatenation, because of the other operand being a String, then the toString method is called on the primitive value, i.e. pv.toString() is used in the expression. The original object's toString method isn't used.

This is because the object's value is more important than its String representation. 

For example:

var myObject1={};
myObject1.valueOf=function(){return 1;};
myObject1.toString=function(){return "One";};

followed by:

"1"+myObject1;

is "11" because valueOf returns 1 which is a primitive value and then 1.toString() is called to give "1" which is used in the concatenation. Object1's toString method doesn't get used. 

Also notice that it doesn't matter which of the two methods returns the primitive value. 

The same sort of thing happens if your custom object returns a String primitive value when the expression needs a Number. In this case the primitive value's valueOf is called in an attempt to obtain a Number primitive.

If this doesn't work the result of the expression is NaN – Not A Number.

Recap

Putting all this together:

  1. JavaScript expressions are evaluated in order of precedence and then left-to-right (in most cases) for equal precedence operators. 

  2. All objects involved in an expression are first converted to a primitive value using valueOf.

  3. If any valueOf method doesn't return a primitive value, i.e. a String or a Number, then its toString method is used to get a primitive value, i.e. a String or a Number. 

  4. If neither valueOf or toString returns a primitive value then there is a runtime error.

  5. If the primitive value obtained in step 2 or 3 is of the wrong type for the operator, then toString or valueOf is called on the primitive type to convert it.

 

 JustJavaScripticon

Built-In Objects and Type Conversion

Built-in objects like String have a predefined valueOf method that returns sensible values for the object.

What is a sensible value for a String?  

The obvious answer is a String. 

What is the sensible value for a Number?

The obvious answer is a Number.

So far so good. 

In both cases valueOf returns the same primitive type as the original object. In a sense a Number and a String are their own object values. 

What happens if a Number is involved in an expression that requires a String?

The answer is that its toString method is called. 

What happens if a Number is involved in an expression that requires a string?

In this case the internal toNumber method is called. You can't make use of the toNumber method but it is automatically called to convert a String to a Number when required. 

Consider, for example:

var a=new Number(2); 
var num=new String("123");
a=a*num; 
alert(a);

In this case when the String object is used in the expression a*num then its default valueOf method is called automatically and it returns a primitive string. Next, internally, the toNumber function is called to convert the value of this string to a number.  If the string cannot be converted then the result is NaN – Not a Number. 



Last Updated ( Monday, 25 June 2018 )