JavaScript comes with primitive and composite Built-in Types. The primitive types are: string
, number
, and boolean
, with these special types: null
, and undefined
. Composite types include object, array, and function (which are all object
types).
From a memory perspective, variables come in two different types: value types and reference types. Boolean values and numbers are value-based types, whereas strings, objects, arrays, and functions are reference types. Let's look at the differences.
Value types occupy a fixed size in memory. A boolean value for example only takes one bit. All numbers in JavaScript are 64-bit floating point numbers, so each number is represented by 8 bytes. A reference type variable holds a reference to the value whose length is not fixed and can be of any size.
Another difference between value and reference types is that value types are copied, passed, and compared by value. Reference types, are copied, passed, and compared by reference, rather than by value. Let's look at value types first:
var x = 1;
var y = x;
console.log(x == y); // => true
console.log(x === y); // => true
x = 6;
console.log(x); // => 6
console.log(y); // => 1
console.log(x == y); // => false
console.log(x === y); // => false
When variable y
is assigned to x
it copies its value
and following the assignment any relationship between x
and y
is severed. So, changing the value of x
has no impact on the value
of y
.
Consider this example where a reference type is copied:
var x = { make: "Toyota" };
var y = x;
console.log(x == y); // => true
console.log(x === y); // => true
x.make = "Ford";
console.log(x.make); // => Ford
console.log(y.make); // => Ford
console.log(x == y); // => true
console.log(x === y); // => true
Following the execution of the second statement in which x
is assigned
to y
, y
refers to the same object that
x
refers to. JavaScript does not create a new copy of that object.
If you make any changes to the underlying object through x
, you can
see these changes through y
and vice-versa.
A string represents an ordered sequence of zero or more 16-bit values. Each value typically represents a Unicode character. Unicode is designed to represent all of the characters found in all human languages.
A string is wrapped in either double or single quotes. Adding a single-quote character within a string that is delimited by double quotes is no problem; the same is true for adding a double-quote character in a single-quote delimited string. Adding a single quote in the latter requires an escape character before the single quote, like so \'. Other common escape characters include \n = newline; \r = carriage return; \t = tab, and \\ = backslash.
A string literal can be split across one or more lines by placing an escape character \ (called a continuation character) at the end of each line except the last one. The \ character does not become a part of the string literal. Here are some examples of string literals:
var s1 = "Don't ignore Peter's feedback";
var s2 = 'Don\'t ignore Peter\'s feedback';
var s3 = 'Andrew Fuller\n Bob Springsteen';
var s4 = "Andrew Fuller, \
Bob Springsteen, \
Helena Williams";
console.log(s1);
console.log(s2);
console.log(s3);
console.log(s4);
Note that using the continuation character is generally not recommended.
Here are some other string members you frequently use: length
, and
charAt
.
var s = "Paris, London, Amsterdam";
console.log(s.length); // => 24
console.log(s.charAt(0)); // => P. First character
console.log(s.charAt(s.length - 1)); // => m. Last character
And here are some additional frequently used string methods: indexOf
,
lastIndexOf
, toLowerCase
, substring
,
replace
, and split
.
var s = "Paris, London, Amsterdam";
// Gets position of first 'a', returns 1
console.log(s.indexOf("a"));
// Gets position of first 'a' starting at 3, returns 22
console.log(s.indexOf("a", 3));
// Gets position of last 'o', returns 11
console.log(s.lastIndexOf("o"));
// Converts string to lower-case
console.log(s.toLowerCase());
// Gets substring starting from the 15th character to the last,
console.log(s.substring(14, s.length));
// Replaces "London" with "Berlin"
console.log(s.replace("London", "Berlin"));
// splits into an array of substrings using ", " separator
console.log("Array: " + s.split(", "));
When comparing two strings they are considered equal when they have the same length and the same sequence of characters in corresponding positions.
var str1 = "Hello World";
var str2 = "Hello" + " World";
console.log(str1 == str2); // => true
console.log(str1 === str2); // => true
When we say that strings are immutable it means that once created, the contents of a string is of fixed length and cannot be modified. String may appear mutable when you work with them but they are not.: they are immutable internally. JavaScript does not offer any method or property that lets you alter the contents of a string value.
Again, modifying the string may appear to work, but in fact, a new string is generated.
In the following example, b
is referencing the same string as a
.
However, when modifying the underlying string through the b
reference, a new string
is created internally and its reference is assigned to b
without affecting the
original string referenced by a
.
var a = "Hey";
var b = a;
b += ", what's up";
console.log(b); // => Hey, what's up
console.log(a); // => Hey
String methods like replace
and toLowerCase
appear to
alter the string on which they operate, but they also return new strings.
The boolean type has two literal values: true and false. Note that true and false are language keywords and are not the same as 1 and 0.
All types of values in JavaScript have boolean equivalents. An empty string, null, undefined, NaN, 0, -0, and false itself evaluate to the boolean value false. All these types and their values are referred to as falsy. On the other hand, a non-empty string, any non-zero number including Infinity, any object, and true itself evaluate to the boolean value true. These types and their values are referred to as truthy. Although truthy and falsy are unofficial terms, they are widely used in the JavaScript community.
JavaScript has a special boolean casting function that is used to convert a value into its boolean equivalent – essentially determining whether the passed in expression is truthy or falsy.
var empty = "";
console.log(Boolean(empty)); // => false
var nonEmpty = "JavaScript is cool!";
console.log(Boolean(nonEmpty)); // => true
Automatic conversions to boolean equivalents are common in conditional statements.
var car = { make: "Toyota" };
var display = true;
if (car && display) { // => true
console.log(car.make);
}
car = null;
if (car) { // => false
console.log("drive my car");
}
The first if statement returns true and therefore the alert displays. The second if-statement returns false and does not get executed.
Variables of type string, number, and boolean have properties and methods, but they are not objects. When you read a property or method from these types, JavaScript creates a temporary object, called a wrapper object, by calling the String(), Number(), or Boolean() constructor behind the scenes. Note that you can also explicitly call these constructor functions and create wrapper objects.
var message = "Hello World";
message.howlong = message.length; // => sets property on object
console.log(message.howlong); // => undefined
When the second statement is executed, JavaScript creates a temporary String wrapper object. Then it adds a user-defined property called howlong on it, sets its value, and subsequently discards that object. This shows that String objects are not true objects because they do not accept new properties.
In summary, you cannot set properties to numbers, strings, or booleans; any modification on the wrapper objects is not permanent.
JavaScript offers three ways to explicitly convert a string to a number. They are the
Number
constructor function, parseFloat
, and
parseInt
. The latter two functions have some special behavior.
Here is an example using the Number constructor function which takes a string argument:
var num = Number("1.73");
console.log(num); // => 1.73
The parseFloat
function converts strings to floating point numbers. It ignores
any non-numeric values that appear after numeric characters:
console.log(parseFloat("1.73")); // => 1.73
console.log(parseFloat("USD 1.73")); // => NaN
console.log(parseFloat("1.73 USD")); // => 1.73
The parseInt
function converts string to integer values. It also ignores any
trailing non-numeric values:
console.log(parseInt("1.73")); // => 1, rounded down
console.log(parseInt("USD 1.73")); // => NaN
console.log(parseInt("1.73 USD")); // => 1
console.log(parseInt("0x10")); // => 16. interpreted as hex
Here are some additional conversion methods: parseInt also lets you specify the base of the number. If you want JavaScript to treat your numeric string as base 10 number, pass 10 as the second parameter to parseInt(). Pass 8 if the string is an octal number.
console.log(parseInt("1.73", 10)); // => 1
console.log(parseInt("10", 16)); // => 16
console.log(parseInt("111", 2)); // => 7
console.log(parseInt("16", 8)); // => 14
When reporting monetary values, you are likely to perform number-to-string conversions. In the output
string, you may like to standardize the number of decimal places by rounding the trailing digits or
padding with zeros. The Number object offers methods that you can use to convert numbers to strings.
For example, the toFixed
method converts it to a string while keeping a
number of decimals.
var num = 7.679;
console.log(num.toFixed(0)); // => "8" rounded to nearest whole number
console.log(num.toFixed(2)); // => "7.68"
console.log(num.toFixed(4)); // => "7.6790"
Here are two additional conversion methods: toPrecision
and
toExponential
.
var num = 17305.73;
console.log(num.toPrecision(3)); // => "1.73e+4"
console.log(num.toPrecision(5)); // => "17306"
console.log(num.toPrecision(6)); // => "17305.7"
console.log(num.toPrecision(8)); // => "17305.730"
console.log(num.toExponential(1)); // => "1.7e+4"
console.log(num.toExponential(3)); // => "1.731e+4"
For mathematical computations you use the Math object. There is no need to create an instance of
Math to access its properties and methods because it is a static object. You simply use the Math object
directly and call its method or property names. Below are max
,
min
and abs
methods:
console.log(Math.max(1, 2)); // => 2
console.log(Math.min(1, 2)); // => 1
console.log(Math.abs(-2)); // => 2
Next are some trigonometry related items: the constant PI, and sin and cos.
console.log(Math.PI); // => value of pi
console.log((180 / Math.PI) * Math.sin(1)); // => 90 (degrees)
console.log((180 / Math.PI) * Math.cos(0)); // => 90 (degrees)
Finally some rounding methods:
console.log(Math.round(Math.PI)); // => 3, round up/down to nearest whole nbr
console.log(Math.floor(9.69)); // => 9, round down to nearest whole number
console.log(Math.ceil(9.69)); // => 10, round up to nearest whole number
To perform date and time calculations you use the Date object. The Date object holds a date as the number of milliseconds that have passed since Jan 1 1970 12:00 AM UTC. If you create a new Date object it will be set to the current date and time in the browser.
var current = new Date();
console.log(current); // => current date and time
The time zone is determined by the system settings. In the example below, let's assume that the time zone where this code is run is set to Paris i.e. UTC + 1:00. Depending on your timezone your results will differ.
// => Jan 02 2011, 6:55:42 PM local time
var date = new Date(2011, 0, 2, 18, 55, 42);
console.log(date.getDay()); // => 0. 0–Sunday, 1–Monday, and so on
console.log(date.getDate()); // => 2. 2nd day of the month
console.log(date.getMonth()); // => 0. 0–January, 1–February, and so on
console.log(date.getFullYear()); // => 2011.
console.log(date.getUTCHours()); // => 17. Paris is 1:00 hour ahead from UTC
The difference between two dates is returned in milliseconds.
// => Jan 01 2011 12:00:00 AM local time
var from = new Date(2011, 0, 1);
// => Jan 02 2011, 6:55:42 PM local time
var to = new Date(2011, 0, 2, 18, 55, 42);
var timeElapsed = to - from;
console.log(timeElapsed); // => 154542000 milliseconds
Here are examples of formatting date and time. Please note that your returns will differ depending on your timezone:
// => Jan 02 2011, 6:55:42 PM local time
var date = new Date(2011, 0, 2, 18, 55, 42);
console.log(date.toString()); // => Sun Jan 2 18:55:42 CST 2011
console.log(date.toDateString()); // => Sun Jan 2 2011
console.log(date.toTimeString()); // => 18:55:42 CST
console.log(date.toLocaleDateString()); // => Sunday, January 02, 2011
console.log(date.toLocaleTimeString()); // => 6:55:42 PM
console.log(date.toUTCString()); // => Mon, 3 Jan 2011 00:55:42 UTC
Be careful when you enter an invalid date like January 32, 2011. Most browsers silently changes it to February 1.
console.log(new Date(2011, 0, 32)); // => Feb 1, 2011