There are situations in a programmer’s life when variables need to be converted from one type to another type. Due to THE Book of the Master of Variables, all the variables that he creates can be transformed in one way or another from one type to another type. This type conversion is also called casting.
But before moving on, I would highly recommend you take the quiz on type conversion and see how good you already are. When ready with the quiz, go on with this article.
In order to define all the possible situations, we’ll take each data type and see how to convert variables of other data types into the selected data type.
[something] => String
Strings, as you already know, are sequences of characters enclosed in pairs of '
or "
characters. Converting other data types to strings is pretty easy and straightforward, except some specific cases.
Generally speaking, however, you can convert a value from another data type to string in two ways:
- Use the
toString()
method. - Use the
String
global object.
We’ll discuss both these ways in the sections that follow.
Number => String
The results of converting a number to a string should be of no surprise to you.
var x = 144;
var y = 3.14;
console.log(x.toString()); // '144'
console.log(y.toString()); // '3.14'
// You can also call the `toString()` method directly on a number
console.log(10.toString()); // '10'
console.log(.3.toString()); // '0.3' <- note the added zero it is 0.3 after all
console.log((9.).toString()); // '9.0' <- you can also write even 9..toString()
// Actually, anything that has the type 'number' can be easily casted to String.
console.log(Infinity.toString()); // 'Infinity'
console.log(NaN.toString()); // 'NaN'
console.log((-Infinity).toString()); // '-Infinity'
You will receive the same results when using the String
global object.
console.log(String(42)); // '42'
Boolean => String
Booleans are also pretty intuitive. You will get what you expect when converting a boolean into a string.
console.log(true.toString()); // 'true'
console.log(false.toString()); // 'false'
console.log(String(true)); // 'true'
console.log(String(false)); // 'false'
Null, Undefined => String
Here come the first gotchas. In JavaScript, the null
and undefined
values do not have a toString()
method. In order to cast them to strings you need to use the global String
object.
console.log(String(null)); // 'null'
console.log(String(undefined)); // 'undefined'
// Using the `.toString()` method will result in an error
console.log(null.toString()); // TypeError: Cannot read property `toString` of null
console.log(undefined.toString()); // TypeError: Cannot read property `toString` of undefined
Note that starting in JavaScript 1.8.5, you can call the toString()
method on null
and undefined
values. The results are [object Null]
and [object Undefined]
.
Object => String
Let’s go now for the weird things. Suppose you have the following object:
var planet = { name: 'Earth' };
What do you think its string representation will look like?
console.log(planet.toString()); // '[object Object]'
// Other objects look the same
console.log({}.toString()); // '[object Object]'
console.log({a: 1}.toString()); // '[object Object]'
This is explained by the fact that the toString()
method in JavaScript is inherited by every object descended from Object
. And since our planet
object is an object (good job, Captain Obvious!) it automatically inherits the default toString()
method, which by default returns "[object type]"
, where type is the object type, in our case Object
.
But why "[object Object]"
? Why not, for instance, "{ name: 'Earth' }"
or "planet Earth"
?
You see, sometimes it is safer and easier to set a universal default and let each programmer define its own required behavior of object representation as a string. The toString()
method should return a string representing an object (or a number, in case of numbers, a boolean, in case of booleans, etc.). Therefore, whenever you need to have a specific object to string representation, just override the toString()
method.
planet.toString = function () {
return 'planet name - ' + this.name;
}
console.log(planet.toString()); // 'planet name - Earth'
There is, however, a peculiar behavior.
console.log(planet); // {name: 'Earth'}
console.log('Our planet: ' + planet); // 'Our planet: planet name - "Earth"'
In the first case, the console.log()
statement does not require your object to be represented as a string, therefore it is represented as an object. However, if you do console.log('Our planet: ' + planet)
, then, according to the string concatenation rules that we’ll discuss in the next chapter, the planet
object is casted to string by automatically calling the toString()
method on it in the background.
Now, you might wonder how to define a custom toString()
method on all our objects. The short answer is that generally you won’t need one all the time and it can be achieved easier by defining it one time for a group of similar objects. The long answer will be addressed in one of the following chapters, when we will discuss about object constructors.
Array => String
Arrays have also some interesting behaviors when converted to strings. But generally, the process is pretty straightforward. As you already know, arrays are objects, too, in JavaScript. However, the Array
object overrides the toString
method inherited from Object
. Let’s see how it functions.
var numbers = [1, 2, 33, 'abc', true, false];
console.log(numbers.toString()); // "1,2,33,abc,true,false"
Each element from an array is transformed into a string and they are all concatenated using a ,
comma character.
But check out the following example:
var planet = {name: 'Earth'};
// 0 1 2 3 4 5 <- arr indexes
var arr = [planet, [3, [4, 5, [6]]], undefined, {}, null, 0];
console.log(arr.toString()); // "[object Object],3,4,5,6,,[object Object],,0"
Initially we had 6 elements in the array, but after calling the toString()
mehtod we have 7 values between commas and 2 empty values! Whooa!
Here is the algorithm which the JavaScript engine executes when converting an array to a string:
When the toString()
method is called, internally it calls the join()
method, that returns the string representation of the array. And here is the simplified algorithm of the join()
method:
- If array length is zero, return the empty string. [stop]
- Take the first element from the array.
- If the element is undefined or null, let R be an empty string, otherwise let R be the result of
element.toString()
. - Let k be 1.
- Repeat, while k < len
- Let S be the concatenation of R and ,
- Let element be the result of array[k].toString().
- If element is undefined or null, let next be an empty string, otherwise let next be the result of
element.toString()
. - Let R be the concatenation of S and next.
- Increase k by 1.
- Return R.
Let’s follow each index from the above example and explain its results according to the algorithm:
- at index 0 we have an object, which we already know returns
"[object Object]"
when thetoString()
method is called on it. R = “[object Object]”; - increase k by 1. k = 1
- concatenate R with a comma. S = “[object Object],”
- at index 1 we have an array with 2 elements:
3
and[4, 5, [6]]
, therefore next will be the result of calling thetoString()
method on the array[3, [4, 5, [6]]]
. This, in turn, will call thejoin()
method on this array, converting it to a string as follows:- take the first element. It is non-null, therefore convert it into a string.
3.toString()
is'3'
. R2 = ‘3’ - take the result and add a comma to it. S2 = ‘3,’
- take the next_i element and convert it into a string.
[4, 5, [6]].toString()
will generate anotherjoin()
call on this array:- take the first element. It is non-null, therefore convert it into a string.
4.toString()
is4
. R3 = ‘4’ - take the result and add a comma to it. S3 = ‘4,’
- take the next_j element and convert it into a string.
5.toString()
is'5'
- let R3 be the concatenation of S3 and next_j. R3 = ‘4,5’
- go to the next element
- add a comma to the result. S3 = ‘4,5,’
- take the next_j element and convert it into a string.
[6].toString()
will generate anotherjoin()
call:- take the first element of the array and convert it to a string.
6.toString()
is'6'
- there are no more elements, therefore return the result, which is
'6'
- take the first element of the array and convert it to a string.
- let R3 be the concatenation of S3 and the next_j element. R3 = ‘4,5,6’
- there are no more elements, return R3
- take the first element. It is non-null, therefore convert it into a string.
- let R2 be the concatenation of S2 and the next_i element. R2 = ‘3,4,5,6’
- there are no more elements, return R2 as the result of converting
[3, [4, 5, [6]]]
to a string;
- take the first element. It is non-null, therefore convert it into a string.
- let R be the concatenation of S and next. R = “[object Object],3,4,5,6”
- increase k by 1. k = 2
- let S equal R and a comma. S = “[object Object],3,4,5,6,”
- the the next element in array is
undefined
, therefore next equals to an empty string - let R be the concatenation of S and next. R = “[object Object],3,4,5,6,”
- increase k by 1. k = 3
- let S equal R and a comma. S = “[object Object],3,4,5,6,,” (note the double comma)
- …
And so on. I think you have understood the flow. Just remember that when casting an array to a string, each element in the array is converted using the toString()
method and joined with all other elements with a comma. The exception to this rule are the null
and undefined
values. If the array contains these values, an empty string will be used instead of them.
The join
method
As mentioned earlier, when calling the toString
method on an array, interally it calls the join
method. But we can call it explicitly as well. Moreover, we can pass the join
method a separator parameter, that will define what character will be between the elements of the array in the resulting string.
var arr = [1, 2, 3];
console.log(arr.join()); // "1,2,3"
console.log(arr.join(':')); // "1:2:3"
console.log(arr.join(' kabo-o-om! ')); // "1 kabo-o-om! 2 kabo-o-om! 3"
Function => String
Functions aren’t very surprising when it comes to representing them as a string. Using the toString()
or the String()
global object to transform a function into a string will simply return the string representation of the function object in the form of a function declaration.
function explode (tntAmount) {
var explosionEffects = true;
loadTnT(tntAmount);
return 'Ka-boo-oom!';
}
var fnExpression = function sleep () { return 'Z-z-z'; };
console.log(explode.toString()); // function explode (tntAmount) {
// var explosionEffects = true;
// loadTnT(tntAmount);
//
// return 'Ka-boo-oom!';
// }
console.log(fnExpression.toString()); // function sleep () { return 'Z-z-z'; };
Conclusion on converting [something] => String
Generally speaking, converting something to a string is pretty easy and obvious, except some cases. However, you will remember them, as they are simple and thus you will be able to say how anything will be transformed into a string without hesitation!
[something] => Number
What can be easier than converting something to a number? Well, for us, humans, it is pretty easy to say whether something written on a piece of paper or monitor is a number or not, but computers need exact instructions. Therefore, JavaScript provides you with several methods to convert something to a number:
- The
parseInt
global function. - The
parseFloat
global function. - The
Number
global object. - The
+
unary operator prepended to a variable.
All these methods are doing the same job, although there are some differences in the way they handle some values.
The first two of them expect a string as an argument, therefore, anything that you will pass into it will be automatically converted to a string as described in the previous section (using the toString()
method).
The last two methods both try to convert the “something” that you provide to them to a number according to some rules (that are different from the rules of parseInt
and parseFloat
).
In order to make the explanation process easier, let’s divide these four methods into two groups:
Group A: parseInt
and parseFloat
methods.
Group B: Number
and +
unary operator methods.
Let’s discuss all these details in concrete scenarios.
String => Number
parseInt
and parseFloat
functions
When converting to number from a string using group A, both these functions expect to parse a string. This means that you should provide the function with a string argument to be parsed and transformed into a number. When these functions receive a string, they trim it (remove any leading and trailing spaces from the string) and start to analyze each character one by one. In case a character can be a part of a number, it is being counted into translation to number and next character is being analyzed. However, once the JavaScript interpreter arrives at a character that cannot be converted to a number (e.g. the letter ‘H’), the convertion process stops and the result is what was converted until that character. Let’s see some examples that will clarify things:
parseInt('23'); // 23
parseFloat('-23'); // -23
// parseInt will stop at the first character that does not refer to an integer.
parseInt('-3.14'); // -3
parseFloat('3.14'); // 3.14
// The conversion process stops once it encounters a character
// that "doesn't belong" to a number
parseInt('12a34.g'); // 12
parseFloat('-4.2-3'); // -4.2
// Anything that these functions cannot parse from the beginning, results in
// Not a Number (NaN), which, as you know, is of type "number" in JavaScript :)
parseInt(''); // NaN
parseFloat('a123'); // NaN
// Even the string "Infinity", "null" and "undefined", that are valid values
// are converted to NaN, because starting from the first character they cannot
// be converted to a valid number.
parseInt('Infinity'); // NaN
parseFloat('null'); // NaN
parseFloat('undefined'); // NaN
Number
and +
unary operator
When converting a string to a number using group B methods, there is another set of rules that apply in the conversion process. In these cases, the string value should strongly adhere to a number representation, otherwise it will be considered as NaN
. See it for yourself:
Number('23'); // 23
+'-23'; // -23
// You can convert variables that hold strings as well.
// Note that you can use variables also with `parseInt` and `parseFloat`.
var pi = '3.14';
Number(pi); // 3.14
+pi; // 3.14
// The whitespace is trimmed before conversion
Number(' -1 '); // -1
+' -1 '; // -1
// The "Infinity" string the only string that starts with a letter and is
// converted to a number different than NaN
Number('Infinity'); // Infinity
+'-Infinity'; // -Infinity
// The empty string is the second string (the first one being the Infinity string
// with plus or minus sign (well, technically this is not "one" string) that the
// methods in group B convert to a valid number. All the rest strings return NaN.
Number(''); // 0
+''; // 0
// Even if the following string can be converted with `parseInt` or `parseFloat`
// functions to 1, it will return NaN using `Number` and `+`, because the string
// as a whole is not a valid number representation.
Number('12abc'); // NaN
+'12abc'; // NaN
Boolean => Number
This one will be short :).
Attentive readers will be able to predict the result of conversion using the functions from group A. As already mentioned, these functions expect a string as an argument, or, if provided something different than a string, convert that something to a string using the toString
method and apply the rules of string => number
conversion.
Therefore, as the true
and false
boolean values have the same string representation of "true"
and "false"
, both parseInt
and parseFloat
will return NaN
parseInt(false); // NaN
parseFloat(true); // NaN
Nevertheless, the situation is different for methods in group B. Here we have special rules for each boolean value.
Number(true); // 1 <- `true` boolean value will always return 1
+false; // 0 <- `false` boolean value will always return 0
Null => Number
The null value can also be converted to a number, but only using the methods from group B, as you should already be able to explain why it won’t work using the methods from group A.
Therefore, the null
value is transformed to number 0
in JavaScript.
Number(null); // 0
+null; // 0
Undefined => Number
It may sound counterintuitive, but the undefined
value is converted to a NaN
value irrespective of the method you use.
parseInt(undefined); // NaN
Number(undefined); // NaN
Object => Number
Transforming objects to numbers finally rehabilitates the group A methods, as you will be able, in a way, to use them as well when converting from objects to numbers.
As mentioned earlier, the parseInt
and parseFloat
global functions expect a string argument that these functions will parse. Therefore, when passing an object to it, it will be converted to a string by means of the toString()
method and the resulting string will be converted to a number, if possible.
var emptyObj = {}; // its string representation in "[object Object]"
var person = {
name: 'Jane',
age: 29,
hobby: 'knitting',
toString: function () {
// `this` keyword refers to the object itself,
// in our case `person`
return this.age + ' years old';
}
};
parseInt(emptyObj); // NaN <- the "[object Object]" string can't be transformed
parseFloat(person); // 29 <- the "29 years old" string is transformed as 29
In real world situations you should not use this method though. It is because of the toString
’s method role. Generally speaking, you override the toString
method of an object to make it more readable when a string representation of that object is required. However, in the above case, when you will need a string representation of the person
object, you will get a number;
// When you want to concatenate a string and an object, JavaScript automatically
// converts the object to a string.
console.log('The person object: ' + person); // 'The person object: 29'
// The purpose of having a good `toString` method is to make the a meaningful
// string representation of the object.
person.toString = function () {
return 'Name - ' + this.name + ', age - ' + this.age +
', hobby - ' + this.hobby;
};
console.log('The person object: ' + person);
// Will log: 'The person object: Name - Jane, age - 29, hobby - knitting'
Therefore, in case you need to transform some objects to numbers, use the methods from group B.
Unlike parseInt
and parseFloat
, the Number
and +
unary operator actualy try to convert the argument you pass to them to a number instead of a string. But let’s see the default behavior first.
Number(person); // NaN
+person; // NaN
In case of objects, there is a method that is supposed to represent an object as a primitive number. Supposed to means that it can do whatever you like, but JavaScript will expect that it return a primitive representation of the object.
// Let's add the `valueOf` method on the `person` object defined earlier
person.valueOf = function () {
return this.age;
};
Number(person); // 29
+person; // 29
The valueOf
method is inherited by every object descended from Object
and by default it returns the object itself. However, in our case we overrode it and when the Number
global object internally tried to convert it to a primitive, the valueOf
method returned the number 29.
Array => Number
As arrays are objects, much of the things described when converting objects => numbers apply to arrays as well.
// `parseInt` expects a string, therefore the array is being converted
// to "1,2,3" and then it is converted to a number.
parseInt([1, 2, 3]); // 1
// The empty array is converted to an empty string. Therefore
// the `parseFloat` has nothing to parse and returns NaN.
parseFloat([]); // NaN
// By default, the `valueOf` called on an array returns the array itself.
// Therefore it is not possible to convert it to a number.
+[1, 2, 3]; // NaN
Conclusion on converting [something] => Number
Converting something to a number is not that hard either in JavaScript. Although there are four methods to do that, two of them expect a string to convert (or convert anything to a string) and the other two try to convert to a number according to another set of rules. It’s easy to remember that parseInt
and parseFloat
expect something to parse—namely a string. They are pretty flexible in converting a string to a number.
The Number
and +
unary operator, on the other hand, require strict representations of strings, otherwise it will be a NaN
. And these two can also convert booleans and null values as well.
[something] => Boolean
Converting to boolean is easier than to string and number, because there are only two possible outcomes after conversion - either true
or false
. There are two ways to convert something to boolean:
Boolean
global object!!
double not operator
Although both of them work the same, the latter is more frequently used, as it is faster to type.
String => Boolean
Any string that is different from the empty string is converted to the true
value, while the empty string is false
.
!!'abc'; // true
Boolean('abra-cadabra'); // true
!!''; // false
Number => Boolean
Any number that is different than 0
and NaN
is converted to true.
!!1.3 // true
!!-10000 // true
!!4e2 // true
!!0 // false
!!Infinity // true
!!-.4 // true
!!NaN // false
Null, Undefined => Boolean
Null and Undefined values will always be casted to false
.
!!null; // false
!!undefined; // false
Object => Boolean
On the other hand, objects are always casted to true
, even if the object is empty.
!!{}; // true
!!{planet: 'Earth'}; // true
Array => Boolean
As arrays are objects in JavaScript, they are also casted to true.
!![]; // true
!![1,2]; // true
Conclusion on converting [something] => Boolean
Converting something to a boolean value is easy, because there are only two possible outcomes. You just need to remember that only 0, NaN, "", null, undefined
values convert to the false
value and all the rest are converted to true
.
[something] => null, undefined
As the null
value is a single value, you can’t have any rules of conversion to it, because it is a single variable, so whatever you will try to convert will be null
. This applies to the undefined
value as well.
[something] => Object
Although you will rarely need to convert a primitive into an object (as objects are key-value pairs and what should be the object representation of number 2?), JavaScript has methods to let you do so.
You will probably be surprised, but in order to cast a primitive into an object, you should use the same global objects that you already know:
- String
- Number
- Boolean
The only difference is that you should use them together with the new
keyword. Let’s analyze some specific examples.
String => Object
Whenever you want to cast a string to an object, use the String constructor.
var str = 'Galaxy';
var objStr = new String(str);
console.log(objStr);
// {
// 0: 'G',
// 1: 'a',
// 2: 'l',
// 3: 'a',
// 4: 'x',
// 5: 'y',
// "length": 6,
// "[[PrimitiveValue]]": "Galaxy"
// }
typeof str; // 'string'
typeof objStr; // 'object'
As you can see, the variable created using new String
is of type “object” as well, and not “string”.
Number => Object
To convert a number to an object, use new Number
.
var nr = 121;
var objNr = new Number(nr);
var objNaN = new Number(NaN);
console.log(objNr); // { "[[PrimitiveValue]]": 121 }
console.log(objNaN); // { "[[PrimitiveValue]]": NaN }
typeof nr; // 'number'
typeof objNr; // 'object'
A number object is represented as a key-value pair where the key is the string "[[PrimitiveValue]]"
and the value is the number itself.
Boolean => Object
Likewise, to cast a boolean into an object, use new Boolean
.
var objBool = new Boolean(true);
console.log(objBool); // { "[[PrimitiveValue]]": true }
typeof true; // 'boolean'
typeof objBool; // 'object'
Array => Object
Well, as arrays are objects, there is no built-in method to convert from one into another, as an array is already of type object. In case that you still need for some reason to convert from an array to an object, like this:
['a', 'b', 'c']
|
V
{
0: 'a',
1: 'b',
2: 'c'
}
or to any other form, you will have to write your own function. This is out of scope of this chapter, therefore we’ll leave this exercise for one of the later chapters.
Conclusion on converting [something] => Object
Converting something to an object turned out to be straightforward, due to the existence of the aforementioned global objects. These global objects are also called object constructors. We will talk about them when getting to know another Hero of Programming. As for now, just remember to use the new
keyword.
[something] => Array
Even if arrays are objects, when speaking about conversion specifically to arrays, there are ways that differ from converting to objects.
String => Array
As arrays are sequences of elements and strings are sequences of characters, we can put to work this sequences thing and convert somehow from string to array.
This is achieved using the split()
string method and it is the inverse of the join
array method.
The split
method has the following syntax:
str.split([separator[, limit]])
separator is an optional parameter that specifies the character(s) to use for separating the string. If a separator is omitted, the returned array will contain only one element — the string itself.
limit is an optional parameter of type integer, that defines how many splits should be made/how many elements the returning array to contain.
Let’s analyze some specific examples.
var arr1 = 'abracadabra'.split();
var arr2 = 'abracadabra'.split('');
var arr3 = 'abracadabra'.split('b');
var arr4 = 'abracadabra'.split('a');
var arr5 = 'abracadabra'.split('zz');
var arr6 = 'This house is my home'.split(' ho');
// If no separator is provided, the resulting array contains the string itself
console.log(arr1); // ['abracadabra']
// If the separator is an empty string, the resulting array is an array of characters
console.log(arr2); // ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a']
// If the separator is a string, the resulting array contains the substrings
// created from removing the separator from the original string
console.log(arr3); // ['a', 'racada', 'ra']
// In case the separator is found right at the beginning or end of string,
// it is still removed and the empty string is inserted into array at the
// beginning or end.
console.log(arr4); // ['', 'br', 'c', 'd', 'br', '']
// In case the separator is not found, the resulting array also contains one
// element that is the string itself
console.log(arr5); // ['abracadabra']
// The separator could be a string of characters longer than one character.
console.log(arr6); // ['This', 'use is my', 'me']
Number => Array
Well, how do you imagine converting a number to an array? If you have a number that has more than one digit, you could possibly think of this type of conversion from 1234
to [1, 2, 3, 4]
, but this is not the number 1234
anymore.
Therefore you can’t convert really a number to an array, because it doesn’t make any sense. The only way you can convert number 1234
to an array is to write it in this way: [1234]
.
Boolean => Array
The same story applies here. A boolean is one value, either true
or false
, therefore you can’t convert that into an array.
Object => Array
There is no built-in method to convert an object into an array. But even if it were, you would need to define how would you like the conversion to occur? Suppose you have the following object:
{
name: 'Steven',
age: 33,
hobby: null,
married: true
}
How would you like to convert it?
['Steven', 33, null, true] // 1
['Steven', 33, false, true] // 2
[['name', 'Steven'], ['age', 33], ['hobby', null], ['married', true]] // 3
['name:Steven', 'age:33', 'hobby:null', 'married:true'] // 4
All these are possible ways to convert the given object that you might want to consider and there are even more possible options. That’s why, partially, there is no built-in method to convert an array into an object, because there are so many possible scenarios that you might need. In this case, it is better to write your own function that will make this conversion. We will do this in the following chapter.
Conclusion on converting [something] => Array
In this section you saw that you can easily convert a string into an array. Numbers, booleans, null and undefined aren’t really convertible to arrays because these are single values and not sequences of something. Objects can be converted into an array, but because there are so many ways to do this, there is no built-in method that would make the conversion, forcing you to write your own method that will fit your needs.
Conclusion on type conversion
This chapter comes to its end. You found out how to transform between different data types. Although it may seem a lot of information (which it is), focus on remembering the rules by which the casting process occurs. And do not worry if you won’t remember everything at once. In the following chapters we ocasionally will recall what we’ve learned in this section, therefore you will have the opportunity to remember them better.
Now, you can take the quiz on type conversion once more (or for the first time) and see how good you understood the material. Do not worry if you can’t score 100 points yet. Learning needs time and persistence, so feel free to reread parts of this article that you feel you understood less and retake the quiz from time to time.