Objects are JavaScript values that can be used to group related data. You can create an object by writing {}
:
let mario = {};
Here is the mario
variable pointing to an object value. Let's add some facts about Mario to the object:
let mario = {
name: "Mario",
species: "Human",
occupation: "Plumber",
origin: "Mushroom Kingdom",
};
From the above example, you can see that the variable mario
points to an object we created. Such an object has four properties:
- the
name
property points to the string value"Mario"
, - the
species
property points to the string value"Human"
, - the
occupation
property points to the string value"Plumber"
, - the
origin
property points to the string value"Mushroom Kingdom"
.
Both variables and properties can be thought of as wires. Unlike variables, however, property wires start from objects and not from your code. In fact, properties belong to a particular object and point to values, rather than containing them.
Property names have the following features:
- They are case sensitive. For example,
name
andName
would be two completely different properties. - A single object cannot have two properties with the same name. For example, our object cannot have two properties named
occupation
. - If you do not know in advance the name of a property, which exists in the code as a string value, you can use the bracket notation
[]
to read it from an object.
Assigning a value to a property
You can also assign a new value to an existing property:
mario.occupation = "Athlete";
You can divide the above code into two parts separated by =
: the left part (wire) and the right part (value). First, you follow the mario
wire, which leads to an object. From this object, you follow the occupation
property. For now, you are not interested in its current value.
Unlike the left side, the right side of an assignment always expresses a value. In this example, the value of the right side is the string value "Athlete"
, which you can summon.
Finally, it is time to perform the assignment, pointing the wire on the left side to the value on the right side. From now on, reading mario.occupation
will result in "Athlete"
.
Missing Properties
You can read the current value of a property using the "dot notation" syntax:
console.log(mario.name); // "Mario"
Here, mario.name
is an expression, a question to JavaScript. To answer it, JavaScript first follows the mario
wire, which eventually leads to an object. From this object, JavaScript follows the name
property, which points to the number value "Mario"
. Thus, mario.name
results in "Mario"
.
What happens if you read a property that does not exist:
console.log(mario.family);
JavaScript calculates an expression such as object.property
in three steps:
- It locates the value to the left of the dot (
.
). - If that value is
null
orundefined
, it throws an error. - It checks whether a property with that name exists in the object:
a. If it exists, the result is the value to which this property points.
b. If it does not exist, the result is
undefined
.
For example, mario
points to an object that does not have a family
property. So mario.family
gives undefined
as an answer. This does not mean that the object has a family
property that points to undefined
. It has only two properties and neither of them is named family
.
Using the same rules, let's try to read a property of a property:
let mario = {
name: "Mario",
origin: "Mushroom Kingdom",
};
console.log(mario.family); // undefined
console.log(mario.family.brother); // TypeError
In this case, there are two dots, so you need to follow the rules twice. First, it is necessary to find the value of mario.family
. To do this, you need to find the value of mario
. The variable mario
points to an object. Therefore, the value of mario
is that object. An object is not null
or undefined
, so it is continued. This object does not have a family
property. Therefore, the value of mario.family
is undefined
.
Now, there is undefined
on the left side of the dot (.
). The rules say that null
or undefined
on the left side is an error. So, you throw an error.
Basically, it is because every expression must result in a value or throw an error.