1. Introduction
JavaScript objects form an integral component of the language, serving as a foundation for organizing and manipulating data effectively. Proficiency in working with objects unlocks the potential to construct intricate applications and harness the complete capabilities of JavaScript.
In this guide, we will explore various aspects of JavaScript objects and dive into their key features, including properties and methods. We'll learn how to create objects, access and modify their properties, and perform operations such as adding, removing, and iterating over properties.
2. JavaScript Objects
In JavaScript, objects are fundamental data structures that allow you to store and organize related data and functions together. An object is a collection of key-value pairs, where each key is a unique identifier for a value or a function, known as properties or methods, respectively. Objects provide a powerful way to model real-world entities and their characteristics.
2.1. Definition of JavaScript Objects and their Purpose
JavaScript objects store data as key-value pairs, where the key acts as the identifier to access the corresponding value or function. The value can be of any JavaScript-supported data type, including strings, numbers, booleans, arrays, or even other objects. Consider the following example:
// Creating an object with key-value pairs
const racer = {
name: "Lewis Hamilton",
team: "Mercedes",
carNumber: 44,
championships: 7,
};
In the above example, the object racer
has properties such as name
, team
, carNumber
, and championships
, each associated with a specific value.
2.2. Key-Value Pairs and Properties in Objects
JavaScript objects store data as key-value pairs, where the key acts as the identifier to access the corresponding value or function. The value can be of any JavaScript-supported data type, including strings, numbers, booleans, arrays, or even other objects.
2.3. Creating Objects Using Object Literals:
One common way to create objects in JavaScript is by using object literals, which provide a concise syntax for defining objects. Here's an example:
// Creating an object using object literal
const team = {
name: "Red Bull Racing",
country: "Austria",
activeSince: 2005,
championships: 4,
};
In this example, we create an object team
with properties like name
, country
, activeSince
, and championships
. Each property is defined within curly braces {}
, with the key-value pairs separated by colons :
.
2.4. Accessing Object Properties with Dot Notation and Bracket Notation:
To access the values stored in object properties, you can use dot notation or bracket notation. Dot notation involves using the dot operator .
followed by the property name. Here's an example:
// Accessing object properties with dot notation
console.log(racer.name); // Output: Lewis Hamilton
console.log(racer.team); // Output: Mercedes
In this case, we access the name
and team
properties of the racer
object using dot notation.
Alternatively, you can use bracket notation by enclosing the property name in square brackets []
. This allows you to dynamically access object properties using variables or expressions. Here's an example:
// Accessing object properties with bracket notation
const propertyName = "name";
console.log(racer[propertyName]); // Output: Lewis Hamilton
const championshipYear = "championships";
console.log(racer[championshipYear]); // Output: 7
In this example, we use bracket notation to access the name
property by storing the property name in the propertyName
variable. We can also use bracket notation to access properties dynamically, such as accessing the number of championships using the championshipYear
variable.
Note: Objects provide a flexible and powerful way to structure and organize data, enabling you to build complex applications. Experiment with different object properties and access methods to deepen your understanding of JavaScript objects.
3. Working with Object Properties
3.1 Modifying Object Properties
When you work with JavaScript objects, it's common to modify their properties dynamically. Let's explore how to do this with three examples:
Example 1:
const player = {
name: "Valentino Rossi",
age: 43,
};
player.age = 44;
console.log(player.age); // Output: 44
In this example, we modify the "age" property of the "player" object by assigning a new value to it. When we directly access the property using dot notation, we can update its value.
Example 2:
const team = {
name: "Los Angeles Lakers",
established: 1947,
};
team["name"] = "Golden State Warriors";
console.log(team.name); // Output: Golden State Warriors
Here, we modify the "name" property of the "team" object by using bracket notation. We can access and update the property value by specifying the property name as a string within square brackets.
Example 3:
const player = {
firstName: "LeBron",
lastName: "James",
};
Object.assign(player, { age: 38 });
console.log(player.age); // Output: 38
In this example, we use the Object.assign() method to add a new property, "age," to the "player" object. This method takes the target object as the first argument and an object containing properties to be added as the subsequent arguments.
3.2 Adding and Removing Properties Dynamically
JavaScript allows us to dynamically add and remove properties from objects. Let's explore three scenarios:
Example 1:
const player = {
name: "Valentino Rossi",
};
player.team = "Yamaha";
console.log(player); // Output: { name: "Valentino Rossi", team: "Yamaha" }
In this example, we dynamically add the "team" property to the "player" object by simply assigning it a value. The property is created if it doesn't already exist.
Example 2:
const team = {
name: "Golden State Warriors",
established: 1946,
};
delete team.established;
console.log(team); // Output: { name: "Golden State Warriors" }
Here, we use the "delete" keyword to remove the "established" property from the "team" object. The "delete" keyword allows us to remove properties from an object.
Example 3:
const player = {};
Object.defineProperty(player, "name", {
value: "Michael Jordan",
writable: false,
});
console.log(player.name); // Output: Michael Jordan
player.name = "Kobe Bryant"; // Error: Cannot assign to read-only property 'name'
In this example, we use the Object.defineProperty() method to add a new property, "name," to the "player" object with specific property attributes. In this case, the "writable" attribute is set to "false," making the property read-only.
3.3 Accessing Nested Object Properties
JavaScript objects can have nested structures with properties inside other objects. Let's see how we can access nested properties with three examples:
Example 1:
const team = {
name: {
city: "Los Angeles",
franchise: "Lakers",
},
};
console.log(team.name.city); // Output: Los Angeles
In this example, the "team" object has a nested "name" object. We can access the nested "city" property by chaining the property access using dot notation.
Example 2:
const player = {
details: {
name: "Stephen Curry",
team: "Golden State Warriors",
},
};
const property = "details";
console.log(player[property].name); // Output: Stephen Curry
Here, we demonstrate accessing a nested property using a variable as the key. By using square brackets, we can access the value of the "name" property within the "details" object.
Example 3:
const user = {
profile: {
address: {
city: "New York",
country: "USA",
},
},
};
const { city, country } = user.profile.address;
console.log(city, country); // Output: New York USA
In this example, we use object destructuring to directly extract the nested properties "city" and "country" from the "user" object's "profile" and "address" objects. This syntax allows us to access the nested properties more conveniently.
3.4 Property Descriptors and Property Attributes
In JavaScript, property descriptors define the attributes of an object's properties. Let's explore three important property attributes:
Example 1:
const obj = {};
Object.defineProperty(obj, "property", {
value: "value",
writable: true,
enumerable: true,
configurable: true,
});
console.log(Object.getOwnPropertyDescriptor(obj, "property"));
/*
Output:
{
value: "value",
writable: true,
enumerable: true,
configurable: true
}
*/
In this example, we use the Object.defineProperty() method to define a new property, "property," on the "obj" object. We set various attributes such as "value," "writable," "enumerable," and "configurable." The Object.getOwnPropertyDescriptor() method allows us to retrieve the property descriptor.
Example 2:
const player = {};
Object.defineProperty
(player, "name", {
value: "Valentino Rossi",
writable: false,
});
player.name = "Marc Marquez"; // Error: Cannot assign to read-only property 'name'
Here, we define the "name" property on the "player" object with the "writable" attribute set to "false." This makes the property read-only, preventing assignment of a new value.
Example 3:
const team = {};
Object.defineProperty(team, "name", {
value: "Golden State Warriors",
enumerable: false,
});
for (const key in team) {
console.log(key); // No output (name property is not enumerable)
}
console.log(Object.keys(team)); // Output: []
In this example, we define the "name" property on the "team" object with the "enumerable" attribute set to "false." As a result, the property is not iterated over in loops and is not included in the keys returned by Object.keys().
Note: Gaining proficiency in modifying object properties, dynamically adding and removing properties, accessing nested object properties, and manipulating property descriptors and attributes will provide you with a strong foundation to effectively work with complex data structures using JavaScript objects.
4. Exploring Object Methods
4.1 Introduction to Object Methods
In JavaScript, object methods are functions that are defined within an object. They allow objects to perform actions or behaviors. Object methods are a powerful way to encapsulate functionality within an object and make the code more modular and organized.
4.2 Creating Methods within Objects
To create a method within an object, you can simply define a function as a property of the object. Let's consider an example:
Example:
const movie = {
title: 'Inception',
director: 'Christopher Nolan',
releaseYear: 2010,
play: function() {
console.log('Playing the movie...');
},
};
In the above code snippet, we have an object called movie
with properties such as title
, director
, and releaseYear
. We also define a method called play
using the function syntax. This method can be invoked later to start playing the movie.
4.3 Invoking Object Methods and Accessing Object Context
Once an object method is defined, it can be invoked using dot notation or bracket notation, similar to accessing object properties. For example:
movie.play(); // Output: "Playing the movie..."
In this example, we invoke the play
method on the movie
object using dot notation. The method executes the code inside its function block, which logs the message "Playing the movie..." to the console.
Inside an object method, the this
keyword refers to the current object itself. It allows us to access other properties and methods of the object from within the method.
4.4 The "this" Keyword and Its Significance in Object Methods
The this
keyword is a special keyword in JavaScript that refers to the context in which a function is executed. In the case of object methods, this
points to the object that the method belongs to. Let's see an example:
const series = {
title: 'Stranger Things',
cast: ['Millie Bobby Brown', 'Finn Wolfhard', 'Winona Ryder'],
greet: function() {
console.log(`Hello, we are the cast of ${this.title}: ${this.cast.join(', ')}.`);
},
};
series.greet(); // Output: "Hello, we are the cast of Stranger Things: Millie Bobby Brown, Finn Wolfhard, Winona Ryder."
In this code snippet, we have an object called series
with properties like title
and cast
, and a method called greet
. Inside the greet
method, we use the this
keyword to access the title
and cast
properties of the series
object.
The this
keyword allows object methods to be more dynamic because it refers to the specific instance of the object that is being used. It enables us to reuse the same method across multiple objects, each with its own set of properties.
Using the this
keyword correctly is crucial for object methods to work properly and access the appropriate object context.
Understanding object methods, creating them within objects, invoking them, and grasping the significance of the this
keyword allows you to harness the full power of JavaScript objects. This knowledge empowers you to write code that is more modular and organized, enhancing the overall quality of your JavaScript programs.
5. Understanding object prototypes
5.1 Definition of Object Prototypes
JavaScript heavily relies on object prototypes for defining and expanding object behavior. Every object created in JavaScript is associated with a prototype object that serves as a blueprint. Let's explore this concept further with an example:
Example 1: Creating a Scientific Prototype
function Scientist(name, field) {
this.name = name;
this.field = field;
}
Scientist.prototype.introduce = function() {
console.log(`Hello, my name is ${this.name} and I work in the field of ${this.field}.`);
};
const marieCurie = new Scientist('Marie Curie', 'Physics');
marieCurie.introduce(); // Output: Hello, my name is Marie Curie and I work in the field of Physics.
In this example, we define a constructor function Scientist
that takes name
and field
as parameters. The introduce
method is added to the Scientist.prototype
, which means that all instances of Scientist
will have access to this method. When we use the new
keyword, we create a new object marieCurie
based on the Scientist
prototype and call the introduce
method on it.
5.2 Creating Objects with Constructor Functions
Constructor functions provide a convenient way to create multiple objects with similar properties and methods. They act as a template to instantiate new objects. Let's see an example:
Example 2: Creating Scientific Objects Using Constructor Functions
function Element(name, symbol, atomicNumber) {
this.name = name;
this.symbol = symbol;
this.atomicNumber = atomicNumber;
}
const hydrogen = new Element('Hydrogen', 'H', 1);
console.log(hydrogen); // Output: Element { name: 'Hydrogen', symbol: 'H', atomicNumber: 1 }
In this example, the Element
constructor function defines the properties name
, symbol
, and atomicNumber
. When we create a new instance of Element
using the new
keyword, the this
keyword inside the constructor function refers to the newly created object. We assign values to the object's properties using the this
keyword, and the object is returned automatically.
5.3 Prototypal Inheritance and the Prototype Chain
Prototypal inheritance is a powerful feature in JavaScript that allows objects to inherit properties and methods from their prototypes. The prototype chain establishes a hierarchical relationship between objects. Let's illustrate this with an example:
Example 3: Prototypal Inheritance and the Prototype Chain
function Organism(name) {
this.name = name;
}
Organism.prototype.describe = function() {
console.log(`${this.name} is an organism.`);
};
function Animal(name, species) {
Organism.call(this, name);
this.species = species;
}
Animal.prototype = Object.create(Organism.prototype);
Animal.prototype.constructor = Animal;
Animal.prototype.sound = function() {
console.log(`${this.name} makes a sound.`);
};
const cat = new Animal('Cat', 'Felis catus');
cat.describe(); // Output: Cat is an organism.
cat.sound(); // Output: Cat makes a sound.
In this example, we have two constructor functions: Organism
and Animal
. The Animal
constructor calls the Organism
constructor using Organism.call(this, name)
to inherit the name
property. We then use Object.create(Organism.prototype)
to set up the prototype chain, linking the Animal
prototype to the Organism
prototype. This allows instances of Animal
to access methods defined in Organism.prototype
, such as describe
. Additionally, we define a sound
method specifically for Animal
instances.
5.4 The Object.create()
Method
The Object.create()
method is a powerful tool for implementing prototype-based inheritance in JavaScript. It creates a new object with a specified prototype. Let's see how it works:
Example 4: Using Object.create()
for Prototype-based Inheritance
const mammal = {
describe: function() {
console.log(`${this.name} is a mammal.`);
}
};
const whale = Object.create(mammal);
whale.name = 'Whale';
whale.sound = function() {
console.log(`${this.name} makes a whale sound.`);
};
whale.describe(); // Output: Whale is a mammal.
whale.sound(); // Output: Whale makes a whale sound.
In this example, we create a mammal
object with a describe
method. When we use Object.create(mammal)
, we create a new object whale
that inherits from the mammal
object. We then define the name
property and the sound
method specifically for the whale
object. The whale
object can access the describe
method defined in its prototype (mammal
).
Note: Object prototypes, constructor functions, prototypal inheritance, and the Object.create()
method are essential concepts in JavaScript that provide powerful tools for creating reusable and extensible code. With a grasp of these concepts, you can efficiently build complex data structures and establish relationships between objects, resulting in flexible code organization.
6. Object Iteration and Manipulation
6.1 Different Techniques for Iterating Over Object Properties
When working with objects in JavaScript, it's indispensable to be able to iterate over their properties effectively. Let's explore three techniques for iterating over object properties:
6.1.1 Using the for...in
loop
for (let key in japan) {
if (japan.hasOwnProperty(key)) {
// Access the property using japan[key]
}
}
Explanation: The for...in
loop iterates over all enumerable properties of an object, including those inherited from its prototype chain. We use hasOwnProperty()
to ensure that only the object's own properties are accessed.
6.1.2 Utilizing Object.keys()
const keys = Object.keys(japan);
keys.forEach((key) => {
// Access the property using japan[key]
});
Explanation: The Object.keys()
method returns an array containing all the enumerable property names of the object. We can then use forEach()
to iterate over the keys and access the corresponding properties.
6.1.3 Leveraging Object.getOwnPropertyNames()
const propertyNames = Object.getOwnPropertyNames(japan);
propertyNames.forEach((name) => {
// Access the property using japan[name]
});
Explanation: Unlike Object.keys()
, Object.getOwnPropertyNames()
returns an array containing all property names, regardless of their enumerability. It allows us to access both enumerable and non-enumerable properties of an object.
6.2 Object.keys()
, Object.values()
, and Object.entries()
Methods
JavaScript provides three handy methods - Object.keys()
, Object.values()
, and Object.entries()
- to extract specific information from objects.
6.2.1 Object.keys()
const keys = Object.keys(japan);
Explanation: Object.keys()
returns an array of the object's enumerable property names. It allows you to quickly retrieve the keys without needing to iterate over the entire object.
6.2.2 Object.values()
const values = Object.values(japan);
Explanation: Object.values()
returns an array of the object's enumerable property values. It provides a convenient way to access the values without explicitly iterating over the object.
6.2.3 Object.entries()
const entries = Object.entries(japan);
Explanation: Object.entries()
returns an array of arrays, where each inner array contains a key-value pair of the object's enumerable properties. It allows you to access both the keys and values simultaneously.
6.3 Modifying Object Properties During Iteration
Sometimes, while iterating over an object, you may need to modify its properties. However, modifying properties directly within a loop can lead to unexpected behavior. To handle this situation correctly, you can create a copy of the object and modify the copy instead.
const originalObject = { name: 'Tokyo', population: 13929286 };
const modifiedObject = {};
for (let key in originalObject) {
if (originalObject.hasOwnProperty(key)) {
modifiedObject[key] = originalObject[key] + '_modified';
}
}
console.log(modifiedObject);
Explanation: In this example, we iterate over the properties of originalObject
and assign modified values to modifiedObject
. By creating a separate object, we ensure that the original object is not modified during the iteration.
6.4 Deep Cloning and Shallow Copying of Objects
There are situations where you need to create a copy of an object. Depending on your requirements, you may choose between deep cloning and shallow copying.
6.4.1 Shallow Copying
const shallowCopy = Object.assign({}, originalObject);
Explanation: Shallow copying creates a new object with the same top-level properties and values as the original object. However, if the original object contains nested objects or arrays, they are still shared between the original and copied objects.
6.4.2 Deep Cloning using JSON
const deepClone = JSON.parse(JSON.stringify(originalObject));
Explanation: Deep cloning creates a completely independent copy of the original object, including any nested objects or arrays. It effectively breaks the reference to the original object and ensures that modifications to the clone won't affect the original.
Note: Deep cloning using JSON has limitations and may not work with objects containing functions or cyclic dependencies.
6.4.3 Deep Cloning using External Libraries
To perform deep cloning with more complex objects or overcome the limitations of JSON-based cloning, you can use external libraries such as Lodash or Underscore.js, which provide dedicated methods like cloneDeep()
.
const deepClone = _.cloneDeep(originalObject); // Using Lodash
Explanation: External libraries like Lodash provide reliable and efficient deep cloning methods that can handle complex objects and edge cases more effectively than JSON-based cloning.
Note: Proficiency in these techniques involving iterating over object properties, employing object methods effectively, and comprehending various object copying approaches establishes a strong groundwork for handling intricate data structures in JavaScript.
7. JSON and Object Serialization
7.1 Introduction to JSON (JavaScript Object Notation)
JSON, short for JavaScript Object Notation, is a lightweight data interchange format that has gained widespread popularity due to its simplicity and compatibility with various programming languages. It provides a standardized way to represent data structures in a human-readable format, making it ideal for data storage, transmission, and interoperability between different systems.
7.2 Converting JavaScript Objects to JSON Strings
In JavaScript, you can convert a JavaScript object into a JSON string using the JSON.stringify()
method. This method takes an object as a parameter and returns a JSON string representation of that object.
Example 1: Converting a JavaScript Object to a JSON String
const player = {
name: "Ichiro Suzuki",
age: 49,
team: "Seattle Mariners"
};
const jsonStr = JSON.stringify(player);
console.log(jsonStr);
In this example, we have an object called player
with properties such as name
, age
, and team
. When we call JSON.stringify(player)
, the object is converted into a JSON string representation. The resulting JSON string is then printed to the console using console.log()
. The output will be: {"name":"Ichiro Suzuki","age":49,"team":"Seattle Mariners"}
.
7.3 Parsing JSON Strings into JavaScript Objects
To convert a JSON string back into a JavaScript object, you can use the JSON.parse()
method. This method takes a JSON string as a parameter and returns the corresponding JavaScript object.
Example 2: Parsing a JSON String into a JavaScript Object
const jsonString = '{"name":"Ichiro Suzuki","age":48,"team":"Seattle Mariners"}';
const player = JSON.parse(jsonString);
console.log(player);
In this example, we have a JSON string representation of an object stored in the jsonString
variable. By calling JSON.parse(jsonString)
, the JSON string is parsed and converted back into a JavaScript object. The resulting object is then printed to the console using console.log()
. The output will be an object with properties name
, age
, and team
containing the corresponding values.
7.4 Handling Complex Object Structures with JSON
JSON is not limited to simple objects; it can handle complex object structures and nested data. When working with complex object structures, you can nest objects within objects or include arrays of objects.
Example 3: Handling Complex Object Structures with JSON
const team = {
name: "Japan National Football Team",
coach: "Hajime Moriyasu",
players: [
{ name: "Shinji Kagawa", position: "Midfielder" },
{ name: "Yuto Nagatomo", position: "Defender" },
{ name: "Yuya Osako", position: "Forward" }
]
};
const jsonStr = JSON.stringify(team);
console.log(jsonStr);
In this example, we have an object called team
with properties such as name
, coach
, and players
. The players
property is an array of objects representing individual players. By calling JSON.stringify(team)
, the entire object structure, including the nested objects and array, is converted into a JSON string. The resulting JSON string is then printed to the console. The output will be the JSON representation of the complex object structure.
JSON provides a flexible and efficient way to handle complex object structures, making it a popular choice for data interchange and storage in various applications and APIs.
Note: JSON and its methods for object serialization allow JavaScript developers to seamlessly convert objects into string representations and parse them back into JavaScript objects as required. This capability greatly simplifies data exchange and enhances interoperability between diverse systems.
8. Getters and Setters for Controlling Object Property Access
8.1 Definition of Getters and Setters
Getters and setters are powerful techniques in JavaScript that allow you to control access to object properties. Getters are used to retrieve the value of a property, while setters are used to set or modify the value of a property. Let's explore how they work with some examples:
Example 1:
const country = {
name: "India",
capital: "New Delhi",
get info() {
return `The capital of ${this.name} is ${this.capital}`;
},
set info(value) {
const [name, capital] = value.split(";");
this.name = name;
this.capital = capital;
}
};
console.log(country.info); // Output: "The capital of India is New Delhi"
country.info = "China;Beijing";
console.log(country.name); // Output: "China"
console.log(country.capital); // Output: "Beijing"
In this example, we have an object called country
with name
and capital
properties. We define a getter info
that provides information about the country and its capital. We also define a setter info
that allows updating both the name and capital at once by splitting a given string.
Example 2:
const language = {
_name: "Mandarin",
get name() {
return this._name;
},
set name(value) {
if (value === "Mandarin" || value === "English") {
this._name = value;
} else {
throw new Error("Invalid language!");
}
}
};
language.name = "English";
console.log(language.name); // Output: "English"
language.name = "Spanish"; // Throws an error: "Invalid language!"
console.log(language.name); // Output: "English"
In this example, we have an object called language
with a private property _name
. We define a getter name
that retrieves the name of the language and a setter name
that allows setting the name only to "Mandarin" or "English". If an invalid language is provided, an error is thrown, and the language remains unchanged.
8.2 Object.defineProperty() for Fine-Grained Property Control
The Object.defineProperty()
method allows fine-grained control over object properties. It enables you to define properties with specific attributes, such as configurability, writability, and enumerability. Let's see how it works:
Example 1:
const city = {};
Object.defineProperty(city, "name", {
value: "Tokyo",
writable: false,
enumerable: true
});
console.log(city.name); // Output: "Tokyo"
city.name = "Osaka"; // Throws an error in strict mode or silently fails in non-strict mode
for (let key in city) {
console.log(key); // Output: "name"
}
In this example, we use Object.defineProperty()
to define the name
property on the city
object. We set the value to "Tokyo", make it read-only by setting writable
to false
, and make it enumerable by setting enumerable
to true
. As a result, the name
property cannot be modified, but it can be accessed and iterated over.
Example 2:
const monument = {};
Object.defineProperty(monument, "name", {
value: "Taj Mahal",
configurable: false
});
console.log(monument.name); // Output: "Taj Mahal"
delete monument.name; // Throws an error in strict mode or silently fails in non-strict mode
Object.defineProperty(monument, "name", {
value: "Great Wall of China"
}); // Throws an error in strict mode or silently fails in non-strict mode
In this example, we define the name
property on the monument
object. We set configurable
to false
, which prevents the property from being deleted or redefined using Object.defineProperty()
. Once defined, the name
property becomes immutable and cannot be modified.
8.3 Object.freeze(), Object.seal(), and Object.preventExtensions() for Object Immutability and Protection
JavaScript provides three methods for object immutability and protection: Object.freeze()
, Object.seal()
, and Object.preventExtensions()
. Let's explore each of them with examples:
Example 1:
const city = {
name: "Seoul",
population: 10000000
};
Object.freeze(city);
city.population = 9000000; // Silently fails in strict mode or throws an error in non-strict mode
console.log(city.population); // Output: 10000000
In this example, we use Object.freeze()
to make the city
object immutable. Any attempts to modify its properties will silently fail in strict mode or throw an error in non-strict mode. The population
property remains unchanged even though we tried to assign a new value to it.
Example 2:
const country = {
name: "Japan",
area: 377972
};
Object.seal(country);
country.area = 400000; // Modifies the area property
country.population = 126500000; // Silently fails in strict mode or throws an error in non-strict mode
console.log(country.area); // Output: 400000
console.log(country.population); // Output: undefined
In this example, we use Object.seal() to seal the
country
object. The existing properties can still be modified, but no new properties can be added. Therefore, modifying the area
property succeeds, but attempting to add the population
property fails.
Example 3:
const continent = {
name: "Asia",
countries: 48
};
Object.preventExtensions(continent);
continent.timezones = 11; // Silently fails in strict mode or throws an error in non-strict mode
console.log(continent.timezones); // Output: undefined
In this example, we use Object.preventExtensions()
to prevent the continent
object from having new properties added to it. The attempt to add the timezones
property fails, and the property remains undefined.
8.4 Object.assign() for Object Merging and Shallow Copying
The Object.assign()
method allows you to merge the properties of multiple objects into a target object. It performs a shallow copy, meaning that nested objects are copied by reference. Let's see how it works:
Example 1:
const target = { a: 1, b: 2 };
const source = { b: 3, c: 4 };
const merged = Object.assign(target, source);
console.log(merged); // Output: { a: 1, b: 3, c: 4 }
console.log(target); // Output: { a: 1, b: 3, c: 4 }
console.log(source); // Output: { b: 3, c: 4 }
In this example, we use Object.assign()
to merge the properties of the source
object into the target
object. The properties of source
overwrite the properties with the same names in target
. The resulting object, merged
, contains the combined properties. The original objects, target
and source
, are also modified.
Example 2:
const obj1 = { a: 6 };
const obj2 = { b: 7 };
const obj3 = { c: 8 };
const merged = Object.assign({}, obj6, obj7, obj8);
console.log(merged); // Output: { a: 6, b: 7, c: 8 }
console.log(obj1); // Output: { a: 6 }
console.log(obj2); // Output: { b: 7 }
console.log(obj3); // Output: { c: 8 }
In this example, we create a new empty object as the target of the Object.assign()
method. This prevents modification of the original objects (obj6
, obj7
, obj8
). The properties from all three objects are merged into the merged
object, resulting in a new object with combined properties.
Example 3:
const city1 = { name: "Tokyo" };
const city2 = { name: "Seoul" };
const merged = { ...city1, ...city2 };
console.log(merged); // Output: { name: "Seoul" }
console.log(city1); // Output: { name: "Tokyo" }
console.log(city2); // Output: { name: "Seoul" }
In this example, we have two objects, city1
and city2
, both with a property named name
. We use the spread syntax (...
) to perform object merging. The resulting merged
object contains the properties from both objects. Since city2
is spread after city1
, its name
property overwrites the same property in city1
in the merged result. The original objects, city1
and city2
, remain unchanged.
Understanding advanced object techniques in JavaScript such as getters and setters, Object.defineProperty()
, object immutability and protection using Object.freeze()
, Object.seal()
, and Object.preventExtensions()
, as well as object merging and shallow copying with Object.assign()
, empowers you to control object properties, enhance object behavior, ensure data integrity, and manipulate objects effectively in your JavaScript applications.
9. Exercises: JavaScript Objects (Asia Edition)
Exercise 1:
Create an object called "country" with the following properties:
name
(string)population
(number)capital
(string)languages
(array)
Add a method called addLanguage
to the object that takes a language name as a parameter and adds it to the languages
array.
Exercise 2:
Create an object called "food" with the following properties:
name
(string)cuisine
(string)price
(number)isSpicy
(boolean)
Add a method called isAffordable
to the object that returns true
if the price of the food is below a certain threshold (e.g., 50), and false
otherwise.
Exercise 3:
Create an object called "monument" with the following properties:
name
(string)location
(string)yearBuilt
(number)
Add a method called getAge
to the object that calculates and returns the age of the monument (current year minus yearBuilt).
Exercise 4:
Create an object called "sport" with the following properties:
name
(string)type
(string)players
(number)
Add a method called isTeamSport
to the object that returns true
if the sport is a team sport (e.g., football), and false
if it is an individual sport (e.g., tennis).
Exercise 5:
Create an object called "city" with the following properties:
name
(string)population
(number)area
(number)
Add a method called calculatePopulationDensity
to the object that calculates and returns the population density of the city (population divided by area).
10. Solutions: JavaScript Objects (Asia Edition)
Exercise 1:
const country = {
name: "Japan",
population: 126500000,
capital: "Tokyo",
languages: ["Japanese"],
addLanguage(language) {
this.languages.push(language);
}
};
country.addLanguage("English");
console.log(country.languages);
Explanation: In this exercise, we create an object called "country" with properties such as "name", "population", "capital", and "languages". We also add a method called "addLanguage" to the object, which takes a language name as a parameter and adds it to the "languages" array. In the example, we invoke the "addLanguage" method to add the language "English" to the "languages" array. Finally, we log the updated "languages" array to the console.
Exercise 2:
const food = {
name: "Sushi",
cuisine: "Japanese",
price: 30,
isSpicy: false,
isAffordable() {
return this.price < 50;
}
};
console.log(food.isAffordable());
Explanation: In this exercise, we define an object called "food" with properties such as "name", "cuisine", "price", and "isSpicy". We also add a method called "isAffordable" to the object, which checks if the price of the food is below a certain threshold (in this case, 50) and returns true or false accordingly. In the example, we call the "isAffordable" method and log the result to the console.
Exercise 3:
const monument = {
name: "Taj Mahal",
location: "Agra, India",
yearBuilt: 1643,
getAge() {
const currentYear = new Date().getFullYear();
return currentYear - this.yearBuilt;
}
};
console.log(monument.getAge());
Explanation: In this exercise, we create an object called "monument" with properties such as "name", "location", and "yearBuilt". We also define a method called "getAge" that calculates and returns the age of the monument by subtracting the "yearBuilt" from the current year. In the example, we invoke the "getAge" method and log the result to the console.
Exercise 4:
const sport = {
name: "Football",
type: "Team",
players: 11,
isTeamSport() {
return this.type === "Team";
}
};
console.log(sport.isTeamSport());
Explanation: In this exercise, we define an object called "sport" with properties such as "name", "type", and "players". We also add a method called "isTeamSport" that checks if the sport is a team sport by comparing the value of the "type" property with the string "Team" and returns true or false accordingly. In the example, we call the "isTeamSport" method and log the result to the console.
Exercise 5:
const city = {
name: "Tokyo",
population: 13929286,
area: 2190,
calculatePopulationDensity() {
return this.population / this.area;
}
};
console.log(city.calculatePopulationDensity());
Explanation: In this exercise, we create an object called "city" with properties such as "name", "population", and "area". We also define a method called "calculatePopulationDensity" that calculates and returns the population density of the city by dividing the population by the area. In the example, we invoke the "calculatePopulationDensity" method and log the result to the console.
11. Encouragement
Thank you for investing your time in reading this guide! I trust that you have found it informative and beneficial in enhancing your comprehension of JavaScript JavaScript Objects.
Comments
Post a Comment