Just JavaScript - The Object Expression
Written by Ian Elliot   
Thursday, 12 June 2014
Article Index
Just JavaScript - The Object Expression
String Values
Comparison Operators
Functions In Expressions

Type conversion?

By analogy with other languages, most programmers think of this as type conversion. That is, a Number is converted to a String or vice-versa. It is usually referred to as type coersion because in most cases you, nor the data, have any choice in the matter. 

However, there is a better way to think of what is happening. 

JavaScript doesn't have types in the same way that other languages do. It is as type-free as it is possible to get. 

In other languages variables have an assigned type and they can only reference an object of a compatible type. 

In JavaScript variables don't have a type and they can reference any object. 

In this sense JavaScript doesn't support type. 

It does recognize the primitive values - Number, String and Boolean and their associated wrapper objects. These are the only things that work with the standard operators and hence any object that is involved in an expression has to have a primitive value associated with it. When an object is used in an expression it provides its associated primitive value. If that value is the wrong type of primitive value then the system will convert it if it is possible. 

You can think of this as type conversion but it really is a very degraded use of the term when you compare it to the complex type hierarchies that are found in class based language. 

It is better regarded as representation conversion. If you have a String which stores "123" and you want to add 1 to it then you need to change the representation of the number from "123" to 123 and then add 1.

Some Strings are valid representations of numbers and all numbers have a valid String representation.

 

Objects with custom values

Once you are happy with the idea that general objects can have values associated with them you can start to make use of this.

For example :

var digit={ value:"", 
            valueOf:function(){
             if( this.value=="One") return 1;                    if( this.value=="Two") return 2;

                 ...
             return NaN; 
            }
          };

This defines a simple object that represents the digits 1, 2 and so on as words. The valueOf method converts this representation into a Number representation in a very simple way. 

Now you can write things like:

digit.value="One";
var a=1; 
a=a+digit; 
alert(a);

and you will see that digit has worked correctly within an arithmetic expression. 

What you can't do is provide a toString method that will work correctly in all cases. For example:

var digit={value:"",
           valueOf:function(){
              if( this.value=="One") return 1;
              if(this.value=="Two") return 2;
              ...
              return NaN; },
           toString:function(){
              return this.value; }
         };


In this case the toString will work when you try things like alert(digit) but in an expression the valueOf will be called first and this will provide a Number. If a String is required the system will call the Number's toString method not digit's toString. 

Comparison operators

Once you have the idea that first valueOf is called and then the results of toString if necessary then JavaScript expressions become much easier and more logical.

The comparison operators can be used with Number or String but they come in two forms - type-converting and strict.

The type-converting operators fit in with JavaScript's philosophy even if beginners are often warned against using them. 

The rule for the way a type converting comparison operator works is exactly the same as for the addition/concatenation operator. 

If you use a comparison operator and one of the operands is a string then the toString method is called on the value returned by valueOf. 

So for example if myObject is:

 

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

then:

1==myObject;

is true because there are no String objects involved and valueOf returns Number 1. 

Also:

"1"==myObject;

is true because there is a String object involved, valueOf returns Number 1 and 1.toString()  is "1".  

The strict comparison operator === doesn't ever call valueOf and never performs a type conversion by calling toString; it simply compares the two objects for type and value.

In this case both:

1===myObject;

and:

"1"===myObject ;

return false because despite the fact that both objects have the same values they are different types. The 1 is a Number object, the "1" is a String object and myObject is just an instance of Object. 

This is usually where the discussion of equality and strict equality stops and the point is made that strict equality is much safer and logical. However, even strict equality can be more complex than the above example because of the possibility that that its operands are expressions in their own right. 

For example

1 === myObject;

is false because the operands are different objects but

1 === +myObject;

is true because now the right-hand side is an expression and in its evaluation myObject's valueOf method is called and this returns a Number 1 object which is the same as the Number 1 object on the left.

However, notice that:

"1" === +myObject;

is false because the toString conversion isn't called for the valueOf result from myObject but if you write:

+"1" === +myObject;

the result is true because +"1" calls the String's valueOf method before the comparison. 

Note that putting a + in front of anything is an easy way to convert anything into an expression without modifying its value.  

The idea that the strict equality operator takes type into account is only true if its operands are not expressions. 

There is one final complication that you need to be aware of.

JavaScript needs some way of testing to see if two variables reference the same object. Rather than introduce a new reference equality operator the standard operators, both == and === test for reference equality when both operands are references to objects.

What this means is that if you define two objects with valueOf methods:

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

var myObject2={};
myObject2.valueOf=function(){return 1;};

then the tests:

myObject1==1
myObject2==1

return true as the valueOf method is called. If you were to use === the result would be false because the objects are not Number objects and valueOf is not called.

If you now try:

myObject1==myObject2

or:

myObject1===myObject2

the result is false because the two variables do not reference the same object. 

If you want to compare two objects using their valueOf method you have to explicitly make one or both an expression. For example:

myObject1 == +myObject2

or:

+myObject1 === +myObject2

both return true because they need to evaluate the expression and hence valueOf is called and both objects return Number 1. 

However, notice that the strict equality operator will not call toString to make a type conversion but == will.  

The issue of which is best == or === is more complicated and subtle than most accounts explain and they both have dangers that are best avoided by understanding rather than just using one or the other.

The other operators work in the same sort of way but with the usual complication over what less than and greater than mean for a String.

 

Banner

 

<ASIN:0596805527>

 

<ASIN:193398869X>

 

<ASIN:0137054890>

 

<ASIN:1449381871>

 

<ASIN:1430230541>

 



Last Updated ( Sunday, 10 May 2015 )