Data types
What are data types?
Let's take a closer look at values. We already know that values are assigned to variables or constants and that operands can be values. There are different types of values, like strings, numbers, booleans or objects: values are of a certain data type.
The typeof operator can be used to return
a string indicating the data type of its operand: typeof operand or typeof (operand).
let varA = 'John';
let varB = false;
let varC = 1/3;
let typeOfVarA = typeof (varA);
console.log(typeOfVarA); // logs: "string"
console.log(typeof varB); // logs: "boolean"
console.log(typeof varC); // logs: "number"
Some strange JavaScript logic:
accessing an undeclared variable trows a ReferenceError, except when via a typeof operand.
Then it returns "undefined" (note: not the value undefined but the string "undefined").
console.log(typeof someUndeclaredVar); // logs: "undefined"
console.log(someUndeclaredVar); // logs: ReferenceError: someUndeclaredVar is not defined.
All programming languages make use of data structures, but not all in the same way. JavaScript is a dynamically typed and loosely typed programming language. The values have data types, not the variables, constants or properties. In JavaScript any variable can be (re)assigned values of all types.
let myVar;
myVar = "Hello World!"; // value is of data type "string"
console.log(typeof myVar); // logs: "string"
myVar = Math.PI; // Reassigning different value of different type
console.log(typeof myVar); // logs: "number"
In other programming languages variables may be designated (at declaration) to one particular data type, like in Java.
// Code in Java:
public class MyMainClass {
public static void main(String[] args) {
String myVar = "Hello World!"; // declaring a string variable
myVar = 20; // error: incompatible types.
}
}
In JavaScript values are either of primitive data types or of the object data type. Primitives are values of the types: string, number, boolean, undefined, null, BigInt or symbol. All other values are of type object. Later this tutorial much more about primitives and objects.
Literals
Values get to be of a specific data type in multiple possible ways, as will be covered in the next chapters.
Generally the notation of a value needs to be in a specific format corresponding to the data type.
Such representations of values are called literals.
A literal at assignment automatically makes that value of the corresponding data type.
In the example below myVar gets assigned an object via an object literal: two curly brackets enclosing
two property names that both get assigned a string ('Jane' and 'Doe'). The strings are represented as
string literals: they are in quotation marks.
let myVar;
myVar = { firstName:'Jane', lastName:'Doe' }; // value is of data type "object"
console.log(typeof myVar); // logs: "object"
console.log(typeof myVar.firstName); // logs: "string" // type of object property
myVar = 313; // Reassigning different value of different type, using a number literal
console.log(typeof myVar); // logs: "number"
Note that statements enclosed in curly brackets constitute a block statement. However, if JS expects a value (as in the above example) it treats the curly brackets, and what is inside, as an object literal, and not as a block statement.
Numeric literals, string literals and object literals are covered in more detail in the next chapters.
Literals of primitives null and boolean are merely keywords expressing a certain state of the primitive value:
the keyword null as the only literal for the primitive null and the keywords true and false
as the only two literals for the primitive boolean.
In JS undefined is technically not a literal,
but a property of the global object
(later more about this).
let myVar;
myVar = true; // boolean literal: value is of data type "boolean"
console.log(typeof myVar); // logs: "boolean"
myVar = undefined; // technically not an undefined literal. Value is of data type "undefined"
console.log(typeof myVar); // logs: "undefined"
myVar = null; // null literal: value is of data type "null"
console.log(typeof myVar); // logs: "object" // This is generally considered a legacy mistake in JS.
Primitive data types
Primitive values or simply primitives are values of one of the following data types:
- boolean
-
Logical values
trueandfalseare the only two values of the boolean data type. - undefined
- The value
undefinedis the only value of data type undefined. - null
-
Value
nullis the only value of data type null.(PS,
typeof null;returns "object", which is generally considered a legacy mistake in JS.) - string
- String type values are sequences of text, such as "Hello world!" and "" (empty string).
- number
-
Integers (-123, -10, 0, 1235, 2.1e4) and decimal fractions (-512.022, 3.1415, 1e-3) are of the number type. Also
NaN("Not a Number") andInfinityare values of the number type. All values of this data type are stored as double precision floating point numbers.(Note that
NaN(typeof NaN;) is of the data type number. So, "Not a Number" is a number...) - BigInt
-
BigInt is an integer data type, especially for representing large integers, greater than 253 - 1.
Literals for integers of this type are constructed by appending
nto the end of the integer (-123n, -10n, 0n, 1235n). See Floating points in JavaScript for more information on when BigInts can be useful. - symbol
- Represents a unique identifier. Later more about symbols.
Be aware that data types are not generally defined. Different programming languages use data types in different ways. JavaScript only has two numeric data types ("number" and "BigInt"), but Java, for instance, has numeric data types "byte", "short", "int", "long", "float" and "double". And in Java, data type "String" is not a primitive, but an object.
Undefined vs. null
A variable is automatically assigned the value undefined at declaration and before explicit initialization.
Accessing non-existent object properties returns value undefined
(accessing a non-existent object method throws a TypeError).
Also accessing a parameter in a function when the function is called without providing an argument for this parameter returns value undefined.
Explicitly assigning value undefined is possible, but it is more common to use null for explicit assignment
of an "empty value".
let someVar;
console.log(someVar); // logs: undefined
let someObj = {}
console.log(someObj.someProperty); // logs: undefined
let someArray = []
console.log(someArray[0]); // logs: undefined
function someFunc(someParameter) { console.log(someParameter); }
someFunc(); // logs: undefined
let foobar = undefined;
console.log(foobar); // logs: undefined
Value null needs to be explicitly assigned. JS never automatically assigns value null.
Value null is assigned to represent the absence of any value.
let someVar = 313;
someVar = null; // "reset" someVar
console.log(someVar); // logs: null
When converted to a number, value null converts to 0, and undefined converts to NaN ("Not a Number").
Values null and undefined both convert to false in a Boolean context (except in comparison operations).
Values false, 0, null, undefined and NaN (and an empty string) are
called falsy values.
Values null and undefined are called nullish values.
In chapters
Type coercion,
Falsy & truthy and
Nullish
this all will be explained in more detail.
// Next a constructor function (Number()) is used to convert 'null' and 'undefined' into a number.
// Constructor functions will be explained in more detail in a later chapter.
console.log( Number(null) ); // logs: 0
console.log( Number(undefined) ); // logs: NaN
console.log(null == undefined); // logs: true
if (!null) { console.log("this gets returned, because 'not null' converts to 'not false', which is true"); }
Object data type
JavaScript has a number of special standard built-in objects, like the object array.
A function in JavaScript is also an object, although the typeof operator returns "function".
Standard built-in objects are sometimes referred to as "global objects",
not to be confused with the global object (later more about this).
// Object data types:
let myObject = { firstName:'Jane', lastName:'Doe' },
myArray = ["green", "red", "blue"],
myFunction = function() { console.log("Hello World!") };
console.log(typeof myObject); // logs "object"
console.log(typeof myArray); // logs "object"
console.log(typeof myFunction); // logs "function"
In object-oriented programming (OOP) an object represents "something" that has properties and can perform actions, so called methods. For instance, a robot gripper may have properties like maximum and minimum reach or the number of degrees of freedom and methods like "open gripper", "close gripper", "rotate gripper". In JS an object can be defined as shown in the next example (working web application here). Later much more about objects in JavaScript.
// Define object "pen":
const pen = {
// properties:
color: 'black',
lineWidth: 1,
beginX: 0,
beginY: 0,
endX: 100,
endY: 100,
// method:
drawLine: function() {
ctx.beginPath();
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.color;
ctx.moveTo(this.beginX,this.beginY);
ctx.lineTo(this.endX,this.endY);
ctx.stroke();
}
}
// Drawing a red line from (0,0) to (300,200):
pen.color = 'red'; // change property "color" of object "pen".
pen.endX = 300; // change property "endX" of object "pen".
pen.endY = 200; // change property "endY" of object "pen".
pen.drawLine(); // invoke method "drawLine" of object "pen".
Value data types and reference data types
For the sake of convenience, we will use "variable" where we mean "variable, constant or object property" in the rest of this section.
As mentioned earlier, in JavaScript values are either of primitive data types or of the object data type. In JavaScript, one of the differences between the two is determined by how a value is stored in memory. From this perspective we distinguish value data types and reference data types.
Primitives are of the so called value data type. When a primitive value is assigned to a variable, the value is stored in the variable, which can be thought of as a memory address location identified by the name of the variable. Each variable takes its own memory location, holding a value. Reassigning a primitive value to the variable simply overwrites the old value with the new value in the memory location. It is not possible for different variables to reference the same primitive value.
Objects are of the so called reference data type. Object values are not stored in the variable. Object values are stored in a different kind of memory location (heap vs stack memory). Instead of a value, now a pointer or reference is stored in the variable. That reference "points" to the object value stored in the separate memory location. Multiple variables can hold a reference to the same object value.
Primitive values are immutable: they cannot be changed, only be overwritten (by reassignment). Object values are mutable: unlike primitives, they can be changed.
const objectVar = { a: 2 };
objectVar.b = 3;
console.log(objectVar); // logs: { a: 2, b: 3 } // object has been changed, no reassignment.
const primitiveVar = "hello";
primitiveVar = "hi"; // TypeError: invalid assignment to const 'primitiveVar'
In JavaScript primitives comparison and assignment are value based, objects comparison (equality) and assignment are reference based.
// *** value based: ***
const privateVar1 = 2;
const privateVar2 = 2;
// both variables have an equal value:
console.log(privateVar1 === privateVar2); // logs: true
// *** reference based: ***
const objectVar1 = { a: 2 };
const objectVar2 = { a: 2 };
// both variables reference different objects:
console.log(objectVar1 === objectVar2); // logs: false
console.log({ a: 2 } === { a: 2 }); // logs: false
console.log(objectVar1.a === objectVar2.a); // logs: true // value based
Copying a variable holding a primitive simply creates a new variable holding a new equal primitive value. Copying an object however, creates a new variable holding a new equal pointer, pointing to the same object value! Only a comparison for equality of two references to the same object returns true.
const objectVar = { a: 2 };
const objectVarCopy = objectVar;
// Two variables, one single object,
// both objects are pointing to same object:
console.log(objectVar === objectVarCopy); // logs: true
// Changing the object changes it for both variables:
objectVar.a = 20;
console.log(objectVarCopy.a); // logs: 20