Skip to content
wannacode

Your own type

Problem

The prices got mixed up

You are writing the shopping cart of an online store. Every product has a name and a price, so you keep them in two arrays. Index 0 holds the name and price of the first product, index 1 those of the second.

You want the most expensive one first, so you swap the prices:

const names = ["Bread", "Milk", "Coffee"];
const prices = [1.20, 2.10, 7.50];
// Most expensive first: swap the first and the third price.
const temp = prices[0];
prices[0] = prices[2];
prices[2] = temp;
for (let i = 0; i < names.length; i++) {
console.log(`${names[i]}: €${prices[i]}`);
}
Output
Bread: €7.5
Milk: €2.1
Coffee: €1.2

Bread now costs €7.50. The prices are swapped, but the names are not. The two arrays must always change together, but nothing makes you do it. Add a third array for the quantities, and you have to keep three in mind.

The idea

One product, one place

The name and the price are not separate things. They are parts of one product. We want a "product" type, just like there is number for numbers and string for text.

You make a type like that yourself. It is called a class:

class Product {
name;
price;
quantity;
}

The variables in the class are its fields. Every product will have its own name, its own price and its own quantity.

The class is only a description: "every product has a name, a price and a quantity". There is no product yet.

The name of the class starts with a capital letter (Product), and the names of the fields with a lowercase one (name, price). This way you see at once what is a type and what is a value.

The idea

new: from the description to a product

You create a concrete product from the class with new. It is called an object. You reach its fields with a dot:

shop.js
class Product {
name;
price;
quantity;
}
const bread = new Product();
bread.name = "Bread";
bread.price = 1.20;
bread.quantity = 2;
const coffee = new Product();
coffee.name = "Coffee";
coffee.price = 7.50;
coffee.quantity = 1;
console.log(`${bread.name}: €${bread.price * bread.quantity}`);
console.log(`${coffee.name}: €${coffee.price * coffee.quantity}`);
Output
Bread: €2.4
Coffee: €7.5
  • The class is above the code that uses it. A file can have several classes.
  • new Product() creates a new object. Every object has its own fields: the bread and the coffee do not get in each other's way.
  • bread.price is "the price of the bread". You read it and write it like an ordinary variable.
  • const bread means that bread always points to the same object. The fields of the object can still change.

Now the name and the price of the product are in one place. Move the product, and they move together.

Try it

Nothing is filled in

If you create a product and fill in nothing, what is in its fields?

What will the program print?

const item = new Product();
console.log(item.name);
console.log(item.price);
console.log(item.quantity);
Answer

Try it

What is missing?

What goes in the blank so that there is a new product?

const milk =  Product();
milk.name = "Milk";
milk.price = 2.10;

See it

The variable points to the object

You want a sale on coffee, so you make a "copy" to change its price:

const coffee = new Product();
coffee.price = 10;
const sale = coffee;
sale.price = 8;
console.log(coffee.price); // 8
Step by step, in words
  1. new makes the object, and its fields are still undefined. coffee gets an arrow to it.
  2. Follow the arrow from coffee: the price of the object becomes 10.
  3. sale = coffee copies the arrow, not the object. Two arrows, one object.
  4. Follow the arrow from sale: the price in the same object becomes 8.
  5. coffee points to the same object, so it prints 8.

The price of the coffee became 8 too. The reason is that the variable coffee is not the object itself. The object lives separately in memory, and coffee keeps where it is: an arrow to the object. A variable like that is called a reference.

sale = coffee copies the arrow, not the object. Now two arrows point to one object, so the change through sale shows through coffee too.

You saw the same thing in the lesson on arrays: sale = prices gave a second name to the same array. An array is an object too.

The idea

The discount works now

In the "Functions" module, the discount did not work: the function got the price, changed its own parameter, and the change was lost. With an object it is different:

function discount(p, percent) {
p.price = p.price * (100 - percent) / 100;
}
const coffee = new Product();
coffee.price = 10;
discount(coffee, 10);
console.log(coffee.price);
Output
9

The parameter is still a copy, but a copy of the arrow. It points to the same object, so the change to p.price stays after the function too.

More precisely, if you are curious

If the function puts a new object in the parameter, it only moves its own copy of the arrow. The object outside does not change:

function reset(p) {
p = new Product();
p.price = 0;
}
const coffee = new Product();
coffee.price = 10;
reset(coffee);
console.log(coffee.price);
Output
10
That is why people say JavaScript passes everything by value, and for objects the value is the reference.

The idea

null: an arrow to nowhere

A variable may point to no object at all. Then it holds null: "nothing". If you try to read a field through it, there is no object to read it from:

const gift = null;
console.log(gift.name);

The program starts, but it stops with an error when it reaches the line:

Error
TypeError: Cannot read properties of null (reading 'name')

This is the most common mistake with objects. What an "exception" is and how you catch one, you will see in the module "Errors and exceptions".

An array also holds arrows, not the products themselves. new Array(3).fill(null) makes three places that do not point to a product yet. Each one is null until you put new Product() there:

const cart = new Array(3).fill(null);
console.log(cart[0] === null);
cart[0] = new Product();
cart[0].name = "Bread";
console.log(cart[0].name);
Output
true
Bread

Try it

Find the bug

The program should print "Bread" and "Milk". Instead, it prints "Milk" twice. Which line has the bug?

Pick the line with the bug.

Exercise

Your classes

Solve the tasks in your editor. The class goes at the top of the file, and you create the objects in the code below it.

1. Book. A class Book with fields for the title and the author. Create two books and print them.

Output
Under the Yoke by Ivan Vazov
Tobacco by Dimitar Dimov

2. Car. A class SimpleCar with a field for the speed. Create a car (its speed is 0), increase the speed by 10 and print it. Give the field a starting value (speed = 0;): without it, undefined + 10 gives NaN, "not a number". In the lesson "Behavior" this will become a method of the car.

Output
Speed after accelerating: 10

3. The cart. The cart from the first card, this time with an array of three Product objects: bread €1.20 (2 pieces), milk €2.10 (1 piece), coffee €7.50 (1 piece). Print the amount for each line and the total. Create each product with new Product() first, then put it in the array.

Output
Bread x2: €2.4
Milk x1: €2.1
Coffee x1: €7.5
Total: €12

4. Most expensive first. Sort the same cart by price, from the most expensive to the cheapest, with the bubble sort from the lesson on arrays. This time you swap whole products, so the name and the price move together.

Output
Coffee: €7.5
Milk: €2.1
Bread: €1.2

More tasks

  • Student. A class Student with a name and three grades (three fields). Create two students and print the average grade of each.
  • One book, two names. Create a book, store it in two variables and change the title through the second one. Print the title through the first one. Explain in words why it works this way.

Test

Check yourself

1. What is the difference between a class and an object?
2. const sale = coffee; sale.price = 8; What happens to the price of coffee?
3. What is in the array right after const cart = new Array(3).fill(null);?
4. A function takes a product as a parameter and changes its price. Can you see the change after the call?
5. const gift = null; What happens at gift.name?

Made by Ivo Gergov as part of Evo Tech's campaign for accessible programming education ·