Object-oriented programming is one of the dominant paradigms in application development today, and in JavaScript, we can also take full advantage of OOP. At the same time, in relation to JavaScript, object-oriented programming has some peculiarities.
Objects
In past topics, we have worked with primitive data – numbers, and strings, but data does not always represent primitive types. For example, if in our program we need to describe the essence of a person who has a name, age, gender, and so on, then naturally we cannot represent the essence of a person as a number or a string. We need a few lines or numbers to properly describe the person. In this regard, a person will act as a complex structure, which will have separate properties – age, height, first name, last name, etc.
To work with structures like this, JavaScript uses. Each object can store properties that describe its state and methods that describe its behavior
Creating a new object
There are several ways to create a new object.
The first way is to use the constructor Object:
let user = new Object();
In this case, the object is called the user.
An expression new Object()represents a call to a constructor, a function that creates a new object. The new operator is used to call a constructor. Calling a constructor is actually like calling a regular function.
The second way to create an object is to use curly braces:
let user = {};
To date, the second method is more common.
Object properties
After creating an object, we can define properties on it. To define a property, after the name of the object separated by a dot, specify the name of the property and assign a value to it:
let user = {}; user.name = "Tom"; user.age = 26;
In this case, two properties are declared name and age, which are assigned the appropriate values. After that, we can use these properties, for example, to display their values in the console:
console.log(user.name); console.log(user.age);
You can also define properties when defining an object:
let user = { name: "Tom", age: 26 };
In this case, a colon character is used to assign a value to the property, and a comma (rather than a semicolon) is placed after the property definition.
In addition, a shorthand way to define properties is available:
let name = "Tom"; let age = 34; let user = {name, age}; console.log(user.name); // Tom console.log(user.age); // 34
In this case, the names of the variables are also the names of the properties of the object. And in this way you can create more complex structures:
let name = "Tom"; let age = 34; let user = {name, age}; let teacher = {user, course: "JavaScript"}; console.log(teacher.user); // {name: "Tom", age: 34} console.log(teacher.course); // JavaScript
Object Methods
An object’s methods define its behavior or the actions it performs. Methods are functions. For example, let’s define a method that would display a person’s name and age:
let user = {}; user.name = "Tom"; user.age = 26; user.display = function(){ console.log(user.name); console.log(user.age); }; // method call user.display();
As with functions, methods are first defined and then called.
Methods can also be defined directly when defining an object:
let user = { name: "Tom", age: 26, display: function(){ console.log(this.name); console.log(this.age); } };
As with properties, a function reference is assigned to a method using a colon.
To refer to the properties or methods of an object within that object, the this keyword is used . It means a reference to the current object.
You can also use a shorthand way to define methods, where the colon and the word function are omitted:
let user = { name: "Tom", age: 26, display(){ console.log(this.name, this.age); }, move(place){ console.log(this.name, "goes to", place); } }; user.display(); // Tom 26 user.move("the shop"); // Tom goes to the shop
Array Syntax
There is also an alternative way to define properties and methods using array syntax:
let user = {}; user["name"] = "Tom"; user["age"] = 26; user["display"] = function(){ console.log(user.name); console.log(user.age); }; // method call user["display"]();
The name of each property or method is enclosed in quotation marks and square brackets, then they are also assigned a value. For example, user[“age”] = 26.
When referring to these properties and methods, you can either use the dot notation ( user.name) or access it like this:user[“name”]
It is also possible to define properties and methods via array syntax directly when creating an object:
let user = { ["name"]: "Tom", ["age"]: 26, ["display"]: function(){ console.log(user.name); console.log(user.age); } }; user["display"]();
Strings as properties and methods
It should also be noted that the names of the properties and methods of an object are always strings. That is, we could rewrite the previous object definition like this:
let user = { "name": "Tom", "age": 26, "display": function(){ console.log(user.name); console.log(user.age); } }; // method call user.display();
On the one hand, there is no difference between the two definitions. On the other hand, there are cases where wrapping the title in a string can help. For example, if the property name consists of two words separated by a space:
let user = { name: "Tom", age: 26, "full name": "Tom Johns", "display info": function(){ console.log(user.name); console.log(user.age); } }; console.log(user["full name"]); user["display info"]();
Only in this case, to refer to such properties and methods, we must use the array syntax.
Dynamic Determination of Property and Method Names
The array syntax opens up another possibility for us – defining a property name outside of an object:
const prop1 = "name"; const prop2 = "age"; let tom = { [prop1]: "Tom", [prop2]: 37 }; console.log(tom); // {name: "Tom", age: 37} console.log(tom.name); // Tom console.log(tom["age"]); // 37
Thanks to this, for example, you can dynamically create objects with arbitrary property names:
function createObject(propName, propValue){ return { [propName]: propValue, print(){ console.log(`${propName}: ${propValue}`); } }; } let person = createObject("name", "Tom"); person.print(); // name: Tom let book = createObject("title", "JavaScript Reference"); book.print(); // title: JavaScript Reference
Removing properties
Above we saw how you can dynamically add new properties to an object. However, we can also delete properties and methods using the delete operator. And just like adding, we can remove properties in two ways. The first way is to use dot notation:
delete object.property
Or use array syntax:
delete object["property"]
For example, let’s remove the property:
let user = {}; user.name = "Tom"; user.age = 26; user.display = function(){ console.log(user.name); console.log(user.age); }; console.log(user.name); // Tom delete user.name; // remove the property // Alternative option // delete user["name"]; console.log(user.name); // undefined
After deletion, the property will be undefined, so when you try to access it, the program will return undefined.
Const Objects
We may need that the object cannot be changed, that is, made constant. However, simply defining it as a normal constant using the const operator is not enough. For example:
const person = {name: "Tom", age: 37}; person.name= "Bob"; console.log(person.name); // Bob
Here we see that the property of the object has changed its value, even though the object is defined as a constant.
The operator constantly effects that we cannot assign a new value to the constant, for example, as in the following case:
const person = {name: "Tom", age: 37}; person = {name: "Sam", age: 56}; // Error - you cannot assign a value to a constant a second time
However, we can change the values of the properties of an object.
To make an object truly const, you need to use the special Object.freeze() method. An object is passed to this method as a parameter, which must be made constant:
const person = {name: "Tom", age: 37}; Object.freeze(person); person.name= "Bob"; console.log(person.name); // Tom - property value has not changed
Creating an object from variables and constants
When creating an object, its properties can be passed the values of variables, constants, or dynamically calculated results of functions:
function getSalary(status){ if(status==="senior") return 1500; else return 500; } const name = "Tom"; const age = 37; const person = { name: name, age: age, salary: getSalary()}; console.log(person); // {name: "Tom", age: 37, salary: 500}
But if the names of the constants/variables are the same as the names of the properties, then you can shorten the value transfer:
const name = "Tom"; const age = 37; const salary = 500; const person = { name, age, salary}; console.log(person); // {name: "Tom", age: 37, salary: 500}
In this case, the person object will automatically receive properties whose names will correspond to the names of the constants, and as values will have the values of these constants.
The same applies to passing functions to object methods:
function display(){ console.log(this.name, this.age); } const move = function(place){ console.log(this.name, "goes to", place)}; const name = "Tom"; const age = 37; const salary = 500; const person = { name, age, salary, display, move}; person.display(); // Tom 37 person.move("cinema"); // Tom goes to cinema
In this case, the person object has two methods that correspond to the functions passed to the object – display()and move(). It is worth noting that when passing functions to object methods in this way, we can still use the keyword in these functions thisto refer to the functionality of the object. However, you should be careful when passing lambda expressions, because for global lambda expressions, this will represent the browser window object:
const move = (place)=>{ console.log(this.name, "goes to", place); console.log(this);}; const name = "Tom"; const person = { name, move}; person.move("cinema"); // goes to cinema Object.fromEntries() function
Using the Object.fromEntries() function, you can create an object from a set of key-value pairs, where the key will then represent the name of the property. For example, let’s create an object from arrays:
const personData = [ ["name", "Tom"], ["age", 37]]; const person = Object.fromEntries(personData); console log(person); // {name: "Tom", age: 37} console.log(person.name); // Tom
Here the object is created from the personData array, which contains two sub-arrays. Each subarray contains two elements and actually represents a key-value pair. The first element represents the key and the second element represents the value.