null, Objects and arrays of objects

Truthiness and Falsiness

We saw that an uninitialised variable (a variable that has been declared but not assigned a value) receives a value of undefined.

javascript
	let example;
	console.log(example);
	// undefined

In JavaScript, undefined is not the only way to represent an absence of information. There is an important difference between different falsy data types. Consider this selection of falsy values:

  • undefined, the variable is empty and has never been set. It is ‘new’ or ‘pristine’.
  • null, the variable is empty but has been purposefully set to empty.
  • 0, the variable stores an empty quantity.
  • "", the variable stores an empty string.

These values are referred to as falsy, because they are “like false”, when used in a boolean expression:

javascript
	if (null) {
	  console.log("null is truthy");
	} else {
	  console.log("null is falsy");
	}
	
	if (0) {
	  console.log("0 is truthy");
	} else {
	  console.log("0 is falsy");
	}
	
	if ("") {
	  console.log('"" is truthy');
	} else {
	  console.log('"" is falsy');
	}

A convenient way to test whether a value is truthy or falsy is by using the Boolean method:

javascript
	console.log(Boolean("")); // false, therefore falsy
	console.log(Boolean("abc")); // true, therefore truthy

A truthy value represents any positive information. To put it simply:

There is something here

Some of the truthy values may be surprising or seem counterintuitive:

  • [], an empty array
  • {}, an empty object
  • "0", the string of the number zero

Although nothing is contained within an empty array [], the array itself counts as ’ one thing ‘.

The same is true for an empty object {}. Despite having no properties, it counts as “something”.

In the case of "0", this is a valid string with a length of 1. To use this as a number, it should be cast using Number("0").

javascript
	console.log(Boolean([])); // true, therefore truthy
	console.log(Boolean({})); // true, therefore truthy
	console.log(Boolean("0")); // true, therefore truthy

Understanding truthiness is very useful when preventing errors in your code:

javascript
	let listOfPosts = serverResponse.posts; // We don't know exactly what is here
	
	if (listOfPosts) {
	  // We know we have something to work with
	  // It could be an empty array or object
	} else {
	  //nothing was found
	}

Introduction to objects

An object is a data structure that groups values together under a variable name.

Values are stored inside an object by creating a property within the object:

javascript
	let exampleObject = {
	  exampleProperty: "exampleValue",
	};

Syntax and Notation

Objects are a powerful way to describe real-world concepts and allow for a style of coding that is easier to read.

For example, a dog has certain properties like its name, breed, owner and number of legs.

We can represent these properties in an object in JavaScript like this:

javascript
	let dog = {
	  name: "Tripod",
	  breed: "labrador",
	  numberOfLegs: 3,
	  owner: null,
	};

We’ve created a variable called dog with a value type of object. The object has four properties, name, breed, owner and numberOfLegs.

Each property has a key and value separated by a colon : symbol:

javascript
	let example = {
	  key: "value",
	};

An object can have zero or more properties, and it can store any kind of value type - including other objects:

  • string
  • number
  • boolean
  • undefined
  • null
  • array
  • object

Accessing data within an object

We can access an object’s properties using dot . notation.

To reference the dog’s name value:

javascript
	console.log(dog.name);
	// "Tripod"

To reference the dog’s breed value:

javascript
	console.log(dog.breed);
	// "labrador"

Note the difference between these two outputs:

javascript
	console.log(dog.owner);
	// "null"
	
	console.log(dog.colour);
	// "undefined"

We know that there is no owner, but which colour the dog is has never been described.

Adding or updating data in an object

Often an object will be created empty {} first, and data will be added to it later on.

We can use dot notation to set or update the value of any property in an object:

javascript
	let example = {
	  edited: false,
	};
	
	example.edited = true;
	example.text = "I have edited this example";
	console.log(example);
	// { edited: true, text: "I have edited this example" }
Watch on Vimeo Code from the video

Arrays of objects

As mentioned in the previous lesson, using arrays of objects is a powerful pattern that is used by almost every web application.

For example, on an eCommerce website, we need to represent the various products available so that they can be shown as a listing:

javascript
	let product1 = {
	  id: 327,
	  name: "Screwdriver",
	  price: 99.99,
	};
	
	let product2 = {
	  id: 968,
	  name: "Wrench",
	  price: 50.95,
	};

Storing each product in a separate variable is possible, but it makes it difficult to access and work on this information.

Instead, we should group this categorical data together into an array of objects.

Without changing the code above, we can assign the existing product variables to an array:

javascript
	let products = [product1, product2];

Now we have an array of product objects. We can access a specific object based on its index:

javascript
	console.log(products[1]); // { id: 968, name: "Wrench", price: 50.95 }
	console.log(products[1] === product2); // true

We can loop through the array of objects like any other array, using a for loop or array prototype methods:

javascript
	for (let i = 0; i < products.length; i++) {
	  console.log(products[i]);
	  console.log(products[i].name);
	}
	
	products.forEach(function (product, i) {
	  console.log(product, i);
	  console.log(product.name);
	});

It is often helpful to assign local variables inside a for loop to make the code easier to read:

javascript
	for (let i = 0; i < products.length; i++) {
	  let product = products[i];
	  let productName = product.name;
	  console.log(productName);
	}

Instead of defining each product on its own, it is better to define them together - directly into an array:

javascript
	let products = [
	  {
	    id: 327,
	    name: "Product 1",
	    price: 99.99,
	  },
	  {
	    id: 968,
	    name: "Product 2",
	    price: 50.95,
	  },
	];

When receiving data from a remote server in future products, list data will always be returned in the above format rather than in discrete variables.

A list of products containing the objects above sent from a server would look like this. The objects would be placed directly into the array rather than in variables.

This video looks at looping through arrays of objects and includes a practical use for the object properties, i.e. creating HTML from them.

Watch on Vimeo Code from the video

The following content is optional and intended for students who wish to get ahead. The methods and techniques described below will not be part of the marking criteria for this module; however, correctly implementing these is a good way to show understanding.

Finding objects in an array

Often we need to find a specific item from an array of objects, and since they will not be defined in their own variable, we cannot simply reference the variable name.

If we know the position of the object in the array, this is easy. We can use square bracket notation to access the item:

javascript
	let myObject = products[0];

However, we may need this information, for example, if the user is searching for the name of the product.

In this case, we could loop through all of the items and compare our search text with the name property:

javascript
	let myObject; // undefined
	let searchString = "Wrench";
	for (let i = 0; i < products.length; i++) {
	  // Loop through all the products
	  let product = products[i]; // Set a local variable
	  if (searchString === product.name) {
	    myObject = product; // Set the matching object
	  }
	}
	console.log(myObject);

This is quite a lot of code to do something quite simple, so instead, we can employ an array prototype method to make things simpler:

javascript
	let searchString = "Wrench";
	let myObject = products.find(function (product) {
	  return product.name === searchString;
	});
	console.log(myObject);

Filtering objects in an array

Similar to finding one product, we often need to narrow down a list of objects based on certain parameters.

For example, if the user wants to see products that are less than $60, we should exclude the following product1:

javascript
	let myFilteredArray = []; // empty array
	let maximumPrice = 60.0;
	for (let i = 0; i < products.length; i++) {
	  // Loop through all the products
	  let product = products[i]; // Set a local variable
	  if (product.price < maximumPrice) {
	    myFilteredArray.push(product);
	  }
	}
	console.log(myFilteredArray);

Again, this is a lot of code to do, something that is quite common. It can also be written more simply:

javascript
	let maximumPrice = 60.0;
	let myFilteredArray = products.filter(function (product) {
	  return product.price < maximumPrice;
	});
	console.log(myFilteredArray);

Sorting objects in an array

Another common task, especially in eCommerce applications, is rearranging an array of objects based on their properties.

For example, if a user wants to sort products by their price, with the smallest first.

Using a for loop for this task can quickly become very complicated and hard to read.

Instead, the built-in Array.sort() method can be employed to achieve this task quickly:

javascript
	products.sort(function (productA, productB) {
	  if (productA.price > productB.price) {
	    return 1; // Move B "up" in relation to A
	  }
	
	  if (productA.price < productB.price) {
	    return -1; // Move B "down" in relation to A
	  }
	
	  if (productA.price === productB.price) {
	    return 0; // Don't change order
	  }
	});

This method can be used to sort arrays of objects based on any comparable property values.


Lesson Task

There are practice questions in the master branch of this repo.

There are example answers in the answers branch.

Try the exercises before checking the solutions.