Type Conversions



On the classification of programming languages, there’re so-called strongly typed and weakly typed languages. Strong typing and weak typing are relatively speaking. There's no clear-cut distinction between them.

Java are often said to be more strongly typed. This means that Java has less implicit type conversions on operations involving values of different types. For example, the type of Java strings is String and you cannot do the following in Java:
String number1 = "3";
String number2 = "2";
int result = number1 - number2;
In strongly typed languages, you need explicit type conversions or parsing before performing a calculation. For example: 
String number1 = "3";
String number2 = "2";
int result = Integer.parseInt(number1) - Integer.parseInt(number2);
JavaScript is a weakly typed language. The - operator allows subtracting a string to a string.
js> var number1 = '3';
js> var number2 = '2';
js> var result = number1 - number2;
js> result;

1
js> typeof result;
number
js>

Explicit type conversions or parsing of strongly typed languages avoids many errors due to unexpected type conversions but brings in tedious syntax. Weakly typed languages are opposite. They have advantages of brief syntax but have to pay more attention to problems of unexpected type conversions.

JavaScript's primitive types, such as number, string and boolean, will automatically be converted to their corresponding wrapper types, such as Number, String and Boolean, if necessary. For example:  
js> var num = 10;
js> var binary = num.toString(2);
js> binary;
1010
js> var binary = (10).toString(2);
js> binary;
1010
js>


The variable num is assigned 10, but the method toString is available on the instance of Number. The instance of Number is used to wrap the value of num so you get the way to call toString. As for a number literal, you can use () to wrap it and then call toString directly. JavaScript will type-convert it automatically.

Similarly, a string value will be automatically wrapped in an instance of String if necessary. For example: 
js> var text = 'caterpillar';
js> text.toUpperCase();
CATERPILLAR
js> 'caterpillar'.toUpperCase();
CATERPILLAR
js>


The method toUpperCase is available on the instance of String. The execution environment will wrap a string value as an instance of String if necessary, and then allows you to call toUpperCase.

You can create a wrapper object directly. For example:
js> var num = new Number(10);
js> var text = new String('caterpillar');
js> typeof 10;
number
js> typeof num;
object
js> typeof 'caterpillar';
string
js> typeof text;
object
js>


As for methods on the instance of Number, String and Boolean, take a look at:
You can use parseInt and parseFloat to convert a string value into a numeber value. The advantage is that they ignore non-numeric characters in the string tail. For example: 
js> parseInt('10 years old...XD');
10
js> parseFloat('3.14159......');
3.14159
js> parseInt('010', 10)
10
js> parseInt('010', 8)
8
js>


In the above example, Radix 10 and 8 specified to parseInt are necessary. If a string begins with '0x', the radix is 16 (hexadecimal). If a string begins with '0', it's recommended to specify a radix 8 or 10. A string begins with any other values, the radix is 10 (decimal).

If a string represents a number, it can be operated by +, -, *, / operators. But take care, + has a high priority in string concatenation rather than converting them to a number value for addition. As for -, * and /, operands will be converted to number values for subtraction, multiplication and division. For example: 
js> '6' + '2'
62
js> '6' - '2'
4
js> '6' * '2'
12
js> '6' / '2'
3
js>


If boolean values are combined with +, -, * and / to perform mathematical operations, true will be treated as 1, and false as zero. For example:
js> 1 + true;
2
js> 1 + false;
1
js>


The boolean values are very interesting. In conditional expressions, everything can be treated as a boolean value. An easy formula to remember is: The 0, NaN, '', null and undefined are always false , and all other values are true. The 0, NaN, '', null, undefined and, of course, false are so-called "false family".

For example, if a property doesn't exist on an object, trying to get the value will obtain undefined. So, if you want to know whether a property exists on an object, you can do as such:
js> function exist(obj) {
  >     if(obj.x) {
  >         print('x exists.');
  >     } else {
  >         print('x doesn\'t exist.');
  >     }
  > }
js> var o = {};
js> exist(o);
x doesn't exist.
js> o.x = 10;
10
js> exist(o);
x exists.
js>


The undefined will be treated as false in a if statement. To prevent the property x from error evaluation due to being specified as 0, NaN or null, you can do a more strict checking. For example:
js> function exist(obj) {
  >     if(typeof(obj.x) != 'undefined') {
  >         print('x exists.');
  >     } else {
  >         print('x doesn\'t exist.');
  >     }
  > }
js> var o = { x : 0 };
js> exist(o);
x exists.
js>

 
Type conversions also happen in the equality comparison. There are two equality operators, == and ===, in JavaScript, both can be used to test if two values or references are equivalent. Simply speaking, == tries to convert operands into the same type, and then performs the equality comparision. The === operator returns false immediately if operands have different types. For example:
js> '' == 0;
true
js> '' === 0;
false
js> null == undefined;
true
js> null === undefined;
false
js> 1 == true;
true
js> 1 === true;
false
js>

 
Simply speaking, == performs loose comparison, allow comparison after type conversion.  === performs more strict comparison, true is possible only if operands have the same type. It's better to do some test if you're not sure. For example:
js> false == undefined;
false
js>

 
In weakly typed languages, type conversions often happen automatically.  It's better to get your hands dirty doing some tests if you want to avoid error evaluations or operations due to unnecessary type conversions. In the example above, you can also do the conversion explicitly:
js> false == Boolean(undefined);
true
js>