Welcome to Day 7 of our 30-day JavaScript and Node.js learning series! In the previous article, we introduced you to the JavaScript Arrays, and today, we’ll dive deeper into one of the most crucial topics—JavaScript Objects.
Objects are a fundamental data type in JavaScript, serving as building blocks for creating complex applications. Essentially, they are collections of key-value pairs, where keys are known as properties and values can be of any data type. Therefore, understanding objects is crucial for mastering JavaScript programming.
In this comprehensive guide, we’ll delve into the intricacies of objects. To begin with, we’ll explore how to create, access, and modify them. Additionally, we’ll learn how to use them effectively.
Creating Objects
First and foremost, we create objects using various methods in JavaScript. The simplest method is the object literal, where we define an object by enclosing key-value pairs within curly braces. For instance, you can create an object with a few properties by creating an instance of object directly. On the other hand, another common way to create objects is by using a constructor function.
- Object Literal Notation:
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
city: "New York",
greet: function() {
console.log("Hello, my name is " + this.firstName + " " + this.lastName);
}
};
2. By Creating an Instance of Object Directly
const person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.age = 30;
person.city = "New York";
3. Constructor Functions:
function Person(firstName, lastName, age, city) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.city = city;
this.greet = function() {
console.log("Hello, my name is " + this.firstName + " " + this.lastName);
};
}
const person1 = new Person("Alice", "Smith", 25, "Los Angeles");
In addition, JavaScript provides the Object.create()
method, which creates a new object based on a specified prototype. This method is particularly useful when you want to create an object that inherits properties from another object.
Choosing the Right Method
- Object Literal Notation is ideal for creating simple objects with a fixed structure.
- Constructor Functions, on the other hand, are better suited for creating more complex objects with multiple instances and inheritance.
Accessing and modifying Properties
Next, let’s look at how to access and modify object properties. You can retrieve a property using dot notation, like person.name
, or bracket notation, such as person["name"]
. However, if the property you are accessing does not exist, it will return undefined
.
console.log(person.firstName); // Output: John
console.log(person["lastName"]); // Output: Doe
Moreover, you can modify existing properties by simply assigning a new value to them:
person.occupation = "Developer";
Afterwards, if you need to add new properties, JavaScript allows you to do so dynamically. For example, you can add an address property:
person.age = 31;
In addition to this, you can delete properties using the delete
keyword:
delete person.city;
Object Methods
Objects can have methods, which are functions defined within the object itself. Methods are used to perform actions on the object’s data.
Built-in Methods
Furthermore, JavaScript objects come with a variety of built-in methods to help with object manipulation.
Object Manipulation Methods:
Object.assign(target, ...sources)
:- Copies own enumerable properties from one or more source objects to a target object.
- It is important to note does not copy non-enumerable properties (properties set with
enumerable: false
usingObject.defineProperty
). - Overwrites existing properties in the target object with properties from sources, based on property names.
- Returns the modified target object.
- Example:
const person = { name: "John" };
const details = { age: 30, city: "New York" };
const combined = Object.assign(person, details); // combined: { name: "John", age: 30, city: "New York" }
Object.create(prototype[, propertiesObject])
:- Creates a new object that uses the specified prototype object.
- The prototype object is used for property lookup when properties are accessed on the newly created object.
- Optionally, you can provide a second argument,
propertiesObject
, to define specific properties on the new object. - Example:
function Person(name) { this.name = name; }
const person1 = new Person("Alice"); // person1 inherits from Person.prototype
const person2 = Object.create(Person.prototype, { age: { value: 25, writable: true } }); // person2 inherits from Person.prototype with a custom "age" property
Property Definition and Access Methods:
Property Definition
Object.defineProperty(obj, prop, descriptor)
:- Defines a new property directly on an object (
obj
), or modifies an existing property. - Takes three arguments:
obj
: The object to define the property on.prop
: The name of the property (string or symbol).descriptor
: An object that describes the property (with properties likevalue
,writable
,enumerable
,configurable
).
- Example:
- Defines a new property directly on an object (
const person = {};
Object.defineProperty(person, "name", { value: "John", writable: true, enumerable: true });
console.log(person.name); // Output: John
Object.defineProperties(obj, propertiesObject)
:- Defines multiple properties on an object at once.
- Takes two arguments:
obj
: The object to define the properties on.propertiesObject
: An object whose properties will be defined on the target object.
- Example:
const person = {};
Object.defineProperties(person, {
name: { value: "John", writable: true },
age: { value: 30, writable: false }
});
console.log(person.name); // Output: John
person.age = 31; // Throws an error because "age" is not writable
Object.freeze(obj)
:- Prevents modifications to an object’s existing properties (value, writable, configurable).
- Attempts to modify a frozen object’s properties will throw a
TypeError
. - Frozen objects cannot be further modified.
- Example:
const person = { name: "John" };
Object.freeze(person);
person.name = "Alice"; // Throws a TypeError because the object is frozen
Object.preventExtensions(obj)
:- Prevents new properties from being added to an object.
- Existing properties can still be modified.
- Example:
const person = {};
Object.preventExtensions(person);
person.city = "New York"; // Throws a TypeError
Object.seal(obj)
:- It prevents both new properties from being added and makes existing properties non-configurable.
- Similar to
Object.freeze
but allows existing properties to be modified. - Example:
const person = {
name: "Clara"
};
Object.seal(person);
person.city = "New York"; // Throws a TypeError
person.name = "Alice"; // Allowed (existing property can be modified)
delete person.city; // Throws a TypeError
Access Methods:
Object.entries(obj)
:- Returns an array of key-value pairs from an object’s own enumerable properties.
- Each element in the array is an array of [key, value].
- Example:
const person = { name: "John", age: 30 };
const entries = Object.entries(person); // entries: [["name", "John"], ["age", 30]]
Object.getOwnPropertyDescriptor(obj, prop)
:- Returns a property descriptor object for a specified property (
prop
) on an object (obj
). - The descriptor object describes the property’s characteristics (value, writable, enumerable, configurable).
- Example:
- Returns a property descriptor object for a specified property (
const person = { name: "John" };
const descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor); // { value: "John", writable: true, enumerable: true, configurable: true }
Object.getOwnPropertyDescriptors(obj)
:- Returns an object containing all own property descriptors for an object.
- Similar to
Object.getOwnPropertyDescriptor
but returns all properties at once. - Example:
const person = { name: "John", age: 30 };
const descriptors = Object.getOwnPropertyDescriptors(person);
console.log(descriptors); // { name: { ... }, age: { ... } } (details of each property descriptor)
Object.getOwnPropertyNames(obj)
:- Returns an array of all own property names (strings) of an object.
- Only enumerable properties are included.
- Example:
const person = { name: "John", age: 30, _secret: "" }; // _secret is not enumerable by default
const propertyNames = Object.getOwnPropertyNames(person); // propertyNames: ["name", "age"]
Object.getOwnPropertySymbols(obj)
:- Returns an array of all own property names (symbols) of an object.
- Only enumerable properties are included.
- Example:
const person = { name: "John", age: 30, [Symbol.for("secret")]: "" }; // Symbol property
const propertySymbols = Object.getOwnPropertySymbols(person); // propertySymbols: [Symbol(secret)]
Object.getPrototypeOf(obj)
:- Returns the object’s prototype (the object that the current object inherits from).
- If the object has no prototype (e.g.,
Object.create(null)
), it returnsnull
. - Example:
function Person() {}
const person1 = new Person();
console.log(Object.getPrototypeOf(person1)); // Output: Person.prototype
Object.is(value1, value2)
:- Determines if two values are exactly the same.
- Handles special cases like
NaN
,0
, and-0
more reliably than==
.Example
Object.isExtensible(obj)
:- Checks if an object can be extended (new properties can be added).
- Returns
true
if the object is extensible,false
otherwise. - Example:
const person = {};
console.log(Object.isExtensible(person)); // Output: true
Object.preventExtensions(person);
console.log(Object.isExtensible(person)); // Output: false
Object.isFrozen(obj)
:- Checks if an object is frozen (no modifications are allowed).
- Returns
true
if the object is frozen,false
otherwise. - Example:
const person = {};
Object.freeze(person);
console.log(Object.isFrozen(person)); // Output: true
Object.isSealed(obj)
:- It checks if an object is sealed, meaning no new properties can be added, although existing properties can still be modified.
- Returns
true
if the object is sealed,false
otherwise. - Example:
const person = {};
Object.seal(person);
console.log(Object.isSealed(person)); // Output: true
Object.keys(obj)
:- Returns an array of an object’s own enumerable property names (strings).
- Example:
const person = { name: "John", age: 30 };
const keys = Object.keys(person); // keys: ["name", "age"]
Object.setPrototypeOf(obj, proto)
:- Sets the prototype of an object.
- Replaces the existing prototype with the specified
proto
object. - Example:
const person = {};
const personPrototype = { greet: function() { console.log("Hello!"); } };
Object.setPrototypeOf(person, personPrototype);
person.greet(); // Output: Hello!
Object.values(obj)
:- Returns an array of an object’s own enumerable property values.
- Example:
const person = { name: "John", age: 30 };
const values = Object.values(person); // values: ["John", 30]
Custom Methods
Additionally, you can also define your own custom methods on objects:
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
greet: function() {
console.log("Hello, my name is " + this.firstName + " " + this.lastName);
},
getFullName: function() {
return this.firstName + " " + this.lastName;
}
};
Nested Objects
Objects can be nested within other objects. For example, consider the following:
const address = {
street: "123 Main St",
city: "New York",
zipCode: "10001"
};
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
address: address
};
Arrays as Properties
Objects can have arrays as properties:
const person = {
firstName: "John",
lastName: "Doe",
hobbies: ["reading", "hiking", "programming"]
};
Object Prototypes
Objects in JavaScript inherit properties and methods from their prototype. Thus, the prototype chain allows objects to access properties and methods defined on their prototype and parent prototypes.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.greet = function() {
console.log("Hello, my name is " + this.firstName + " " + this.lastName);
};
const person1 = new Person("Alice", "Smith");
person1.greet(); // Output: Hello, my name is Alice Smith
When to Use Prototypes
Prototypes are useful for creating reusable code and implementing inheritance. In fact, they can be especially helpful when you need to define common properties and methods for multiple objects.
Object Copying and Cloning
When you assign one object to another, both variables will reference the same object in memory. As a result, one object will reflect any changes made to the other.
To create a true copy of an object, you can use the Object.assign()
method or the spread operator:
const person = {
firstName: "John",
lastName: "Doe",
age: 30
};
// Using Object.assign()
const personCopy = Object.assign({}, person);
// Using the spread operator
const personCopy2 = { ...person };
Now, personCopy
and personCopy2
are independent copies of the original person
object. Changes made to one copy will not affect the other.
Conclusion
To summarize, JavaScript objects are a powerful feature that allows developers to structure and manage data efficiently. Not only do they provide flexibility through dynamic properties, but their built-in methods also make manipulation and iteration easy. In addition to these capabilities, understanding how to effectively use objects will help you build more organized and maintainable code in your JavaScript projects.
In our next post we will explore ES6+ Features in JavaScript.
Previous Lesson
Day 6: Javascript Arrays
Next Lesson
Day 8: ES6+ Features in JavaScript
Share with your friends