Objects
1. What is an Object?
1. In JavaScript, an object is a collection of key-value pairs,
where keys are strings (or Symbols), and values can be of any
data type, including functions.
2. How to Create an Object?
There are two ways to create Object in Javascript :
1. Object Literal (Recommended) :
2. Object Constructor :
3. Accessing Object Properties.
2. Dot notation (when key is simple):
console.log(user.name);
3. Bracket notation (for multi-word keys or dynamic keys):
console.log(user["name"]); // John
&
console.log(user["first name"]); // John
4. Adding & Removing Properties.
4. Add a new property:
user.isAdmin = true; //isAdmin is added in user
5. Delete a property:
delete user.age;
5. Computed Properties.
6. Property names can be dynamic:
let fruit = "apple";
let bag = { [fruit]: 5 };
console.log(bag.apple); // 5
6. Check if Property Exists.
7. Find "key" in object if "key" is present than return true else
return false :
console.log("age" in user); // true
console.log("salary" in user); // false
7. Looping through an Object.
8. Use for...in loop:
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// keys
alert( key ); // name, age, isAdmin
// values for the keys
alert( user[key] ); // John, 30, true
}
9. Are objects ordered? In other words, if we
loop over an object, do we get all properties
in the same order they were added?
9. Integer properties (keys) are sorted
10. Non-integer properties (keys) keep their original order.
let codes = {
"49": "Germany",
"41": "Switzerland",
"44": "Great Britain",
// ..,
"1": "USA"
};
for (let code in codes) {
alert(code); // 1, 41, 44, 49
}
Object references and copying
1. Objects are Stored by Reference.
11. Objects are not stored directly in a variable; instead, the
variable holds a reference (memory address) of the object.
12. When you copy an object variable, only the reference is
copied, not the object itself.
13. E.g :-
let user = { name: 'John' };
let admin = user;
admin.name = 'Pete'; // changed by the "admin" reference
alert(user.name); // 'Pete', changes are seen from the "user"
reference
2. Comparison by Reference.
14. Two objects are equal (== or ===) only if they reference the
same object.
15. Two independent objects with the same properties are not
equal.
16. E.g :-
let a = {};
let b = a;
console.log(a == b); // true (same reference)
console.log(a === b); //true
let c = {};
console.log(a == c); // false (different objects)
3. const Objects Can be Modified.
17. Declaring an object with "const' means the reference cannot
change, but the object’s properties can still be modified.
18. E.g :-
const user = {
name: "John"
};
user.name = "Pete";
alert(user.name); // Pete
4. Object Cloning (Shallow Copy).
19. We can do shalloe copy of object using :
3. Object.assign() :-
20. Syntax : - Object.assign(target, ...source)
21. It copies the properties of all source objects into the target,
and then returns it as the result.
22. E.g :-
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user);
alert(clone.name); // John
alert(clone.age); // 30
1. Spread Operator (...) : -
23. Another way to clone an object using shallow copy
24. E.g :-
let user = {
name: "John",
age: 30
};
let clone = {...user}
alert(clone.name); // John
alert(clone.age); // 30
5. Deep Cloning (for Nested Objects)
25. Object.assign() and spread syntax do not deeply clone objects
(nested objects are copied by reference).
26. Use structuredClone() or libraries like Lodash (_.cloneDeep)
for deep cloning.
27. E.g :-
let user = {
name: "John",
sizes: { height: 182, width: 50 }
};
let clone = structuredClone(user);
user.sizes.width = 60;
console.log(clone.sizes.width); // 50 (remains unchanged)
Object methods & "this"
1. Object Methods.
28. Objects in JavaScript can have functions as properties, called
methods.
29. Methods define actions that an object can perform.
30. Eg :-
let user = {
name: "John",
age: 30,
sayHi: function() {
alert("Hello!");
}
};
user.sayHi(); // Hello!
31. Methods can also be assigned from pre-declared functions:
let user = {
name: "John",
age: 30,
sayHi: function() {
alert("Hello!");
}
};
user.sayHi(); // Hello!
2. Method Shorthand.
32. JavaScript allows a shorter syntax for defining methods:
let user = {
sayHi() { // Same as sayHi: function() { ... }
alert("Hello");
}
};
33. The shorthand syntax is preferred for cleaner code.
3. this in Methods.
34. Methods often need to access object properties.
35. The keyword this refers to the object calling the method.
36. E.g:-
let user = {
name: "John",
sayHi() {
alert(this.name);
}
};
user.sayHi(); // John
37. Using this ensures the correct reference, even if the object is
reassigned:
let user = {
name: "John",
sayHi() {
alert(this.name);
}
};
let admin = user;
user = null;
admin.sayHi(); // John
4. this is Evaluated at Runtime.
38. The value of this depends on how a function is called, not
where it is defined.
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert(this.name);
}
user.f = sayHi;
admin.f = sayHi;
user.f(); // John
admin.f(); // Admin
39. If a function is called without an object, this is undefined in
strict mode:
function sayHi() {
alert(this);
}
sayHi(); // undefined in strict mode
5. Arrow Functions & this.
40. Arrow functions do not have their own this. Instead, they
inherit this from their surrounding scope.
41. E.g :-
let user = {
firstName: "Ilya",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi(); // Ilya
6. Constructor Functions & new
Operator.
42. Constructor Function :-
43. Constructor functions are used to create multiple
similar objects.
44. They are named with a capital letter and should be
called with the new operator.
45. E.g :-
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
46. How new Works:
47. A new empty object is created and assigned to this.
48. The function body executes, modifying this.
49. The final object is returned.
50. This is equivelent to:-
let user = {
name: "Jack",
isAdmin: false
};
Checking "new.target"
51. We can check if a function was called with new:
function User() {
alert(new.target);
}
User(); // undefined
new User(); // function User { ... }
Returning Objects from Constructor
52. If return is used with an object, that object is returned instead
of this.
53. If return is used with a primitive, it’s ignored.
function BigUser() {
this.name = "John";
return { name: "Godzilla" };
}
alert( new BigUser().name ); // Godzilla
54. And here’s an example with an empty return (or we could
place a primitive after it, doesn’t matter):
function SmallUser() {
this.name = "John";
return; // <-- returns this
}
alert( new SmallUser().name ); // John
Optional chaining '?.'
1. Introduction.
55. Optional chaining (?.) allows safe access to nested object
properties even if an intermediate property doesn’t exist. This
helps prevent runtime errors caused by accessing undefined or null
properties.
56. Note: Old browsers may require polyfills to support this
feature.
2. The "Non-Existing Property" Problem
57. When trying to access deeply nested properties of an object,
we may encounter errors if any intermediate property is undefined.
58. E.g :-
let user = {}; // user object with no "address" property
console.log(user.address.street); // Error!
Since user.address is undefined, accessing street causes an error.
3. Using Optional Chaining (?.)
59. The optional chaining (?.) operator prevents these errors by
stopping the evaluation if the left-hand value is null or undefined,
returning undefined instead of throwing an error.
60. E.g : -
let user = {}; // user has no address
console.log(user?.address?.street); // undefined (no error)
This syntax is clean, avoids repetition, and prevents unexpected
runtime errors.
4. Optional Chaining with DOM Elements
61. In web development, document.querySelector('.elem') returns
null if no such element exists. Accessing its properties without
checking can cause errors.
62. E.g :-
let html = document.querySelector('.elem')?.innerHTML;
// undefined if element does not exist
This prevents errors when attempting to read properties of a non-existent
element.
5. Short-Circuiting Behavior.
63. The optional chaining operator short-circuits the evaluation if
the left-side operand is null or undefined.
64. E.g :-
let user = null;
let x = 0;
user?.sayHi(x++); // sayHi is never called, x remains 0
console.log(x); // 0
Since user is null, the method sayHi is not executed, and x is not
incremented.
6. Other Variants of Optional Chaining.
a) Optional Chaining with Function Calls (?.())
65. If a function might not exist, we can safely call it using ?.().
66. E.g :-
let userAdmin = {
admin() {
console.log("I am admin");
}
};
let userGuest = {};
userAdmin.admin?.(); // "I am admin"
userGuest.admin?.(); // No error, nothing happens
b) Optional Chaining with Bracket Notation (?.[])
67. Used when property names are dynamic.
68. E.g :-
let key = "firstName";
let user1 = { firstName: "John" };
let user2 = null;
console.log(user1?.[key]); // "John"
console.log(user2?.[key]); // undefined
c) Optional Chaining with delete :-
69. We can safely delete a property using ?.
70. E.g :-
delete user?.name; // Deletes user.name if user exists
7. Limitations of Optional Chaining.
a) Cannot Be Used for Assignments :-
71. Optional chaining cannot be used on the left-hand side of an
assignment.
72. E.g :-
let user = null;
user?.name ="John";//Error: Cannot set property of udefined
b) Variable Must Be Declared :-
73. The variable before ?. must be declared; otherwise, it will
throw a ReferenceError.
74. E.g :-
// ReferenceError: user is not defined
user?.address;
JavaScript Symbol Type
Introduction :-
75. A Symbol is a primitive type in JavaScript used to
create unique identifiers for object properties. Symbols are
guaranteed to be unique, even if they have the same
description.
76. Creating a Symbol :-
A Symbol can be created using the Symbol() function:
let id = Symbol();
We can also add an optional description:
let id = Symbol("id");
Even if two symbols have the same description, they are
different:
let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 === id2); // false
Symbols as Object Keys : -
77. Symbols can be used as object property keys to create hidden
properties that cannot be accidentally accessed or overwritten.
78. E.g :
let user = { name: "John" };
let id = Symbol("id");
user[id] = 123;
console.log(user[id]); // 123
Using a symbol prevents property conflicts between
different scripts.
Symbols in Object Literals :-
79. To use a symbol in an object literal, use square brackets:
80. E.g :-
let id = Symbol("id");
let user = {
name: "John",
[id]: 123
};
Symbols and Iteration : -
81. Symbolic properties are ignored by for...in and Object.keys():
82. E.g :-
let user = {
name: "John",
[Symbol("id")]: 123
};
for (let key in user) console.log(key); // Only "name"
83. However, Object.assign() copies symbols:
let clone = Object.assign({}, user);
console.log(clone[Symbol("id")]); // 123
Global Symbols :-
84. To create a global symbol, use Symbol.for(key), which
ensures the symbol is stored in a registry:
let id1 = Symbol.for("id");
let id2 = Symbol.for("id");
console.log(id1 === id2); // true
To retrieve the key of a global symbol:
console.log(Symbol.keyFor(id1)); // "id"
System Symbols :-
JavaScript provides built-in system symbols, such as:
85. Symbol.iterator (for iterables)
86. Symbol.toPrimitive (for type conversion)
Example of Symbol.toPrimitive:
let obj = {
[Symbol.toPrimitive](hint) {
return hint === "string" ? "Object as string" : 100;
}
};
console.log(obj + 10); // 110
* Object.fromEntries :-
87. Object.fromEntries() is a JavaScript method that converts an
array of key-value pairs into an object.
88. It is the inverse of Object.entries(), which converts an object
into an array of key-value pairs.
89. Syntax :- Object.fromEntries(iterable)
90. iterable: An array (or any iterable object) containing key-
value pairs.
91. E.g :-
const entries = [['name', 'Alice'], ['age', 25], ['city', 'New York']];
const obj = Object.fromEntries(entries);
console.log(obj);
// Output: { name: 'Alice', age: 25, city: 'New York' }
* Object.entries(obj) :-
92. The Object.entries(obj) method returns an array of key-value
pairs from an object.
93. Syntax :- Object.entries(obj);
94. obj – The object to convert into an array.
95. Returns an array of [key, value] pairs
96. E.g :-
const user = { name: "Alice", age: 25, country: "USA" };
console.log(Object.entries(user));
/* Output:
[
["name", "Alice"],
["age", 25],
["country", "USA"]
]
*/
// Iterating Over an Object Using Object.entries()
const person = { name: "John", age: 30 };
for (const [key, value] of Object.entries(person)) {
console.log(`${key}: ${value}`);
}
/* Output:
name: John
age: 30
*/
* Object.keys(obj) :-
97. The Object.keys(obj) method returns an array of an object's
keys (property names).
98. Syntax :- Object.keys(obj);
99. obj – The object whose keys (property names) you want to
retrieve.
100. Returns an array of strings representing the object's keys.
101. E.g :-
const user = { name: "Alice", age: 25, country: "USA" };
console.log(Object.keys(user));
// Output: [ 'name', 'age', 'country' ]
// Iterating Over an Object Using Object.keys()
const person = { name: "John", age: 30, city: "New York" };
Object.keys(person).forEach(key => {
console.log(`${key}: ${person[key]}`);
});
/* Output:
name: John
age: 30
city: New York
*/
* Object.values(obj) :-
102. The Object.values(obj) method returns an array of an
object's values (property values).
103. Syntax :- Object.values(obj);
104. obj – The object whose values you want to retrieve.
105. Returns an array of values.
106. E.g :-
const user = { name: "Alice", age: 25, country: "USA" };
console.log(Object.values(user));
// Output: [ 'Alice', 25, 'USA' ]
// Iterating Over an Object Using Object.values()
const product = { id: 101, name: "Laptop", price: 75000 };
Object.values(product).forEach(value => {
console.log(value);
});
/* Output:
101
Laptop
75000
*/
Property Flags and Descriptors
1. Property Flags :-
Every property has 3 special attributes (flags):
107. writable → If true, the value can be changed; otherwise,
it's read-only.
108. enumerable → If true, the property appears in loops like
for...in.
109. configurable → If true, the property can be deleted or its
flags modified.
2. Getting Property Descriptors :-
110. Use Object.getOwnPropertyDescriptor() to get details
about a property.
111. Syntax:-
Object.getOwnPropertyDescriptor(obj, propertyName)
112. E.g :-
let user = { name: "John" };
console.log(Object.getOwnPropertyDescriptor(user, "name"));
/*
value: "John",
writable: true,
enumerable: true,
configurable: true
*/
3. Defining/Modifying Property Flags :-
113. Use Object.defineProperty() to set or modify property flags.
114. Syntax :-
Object.defineProperty(obj, propertyName, descriptor)
115. E.g:-
let user = {};
Object.defineProperty(user, "name", {
value: "John",
writable: false, // can't modify
enumerable: false, // won't appear in loops
configurable: false // can't delete or modify flags
});
4. Flag Behaviors :-
116. writable: false → Property value can't be changed.
117. enumerable: false → Property won't appear in
loops or Object.keys().
configurable: false → Property can't be deleted
or have its flags modified.
118.
E.g :-
let user = { name: "John" };
Object.defineProperty(user, "name", { writable: false });
user.name = "Pete"; // Error: Cannot assign to read-only
property
5. Defining Multiple Properties :-
Use Object.defineProperties() to define multiple
properties at once.
119.
120. Syntax:-
Object.defineProperties(obj, {
prop1: descriptor1,
prop2: descriptor2
});
121. E.g :-
Object.defineProperties(user, {
age: { value: 30, writable: true },
city: { value: "Delhi", enumerable: true }
});
6. Sealing and Freezing Objects :-
a) Object.preventExtensions() :-
122. Object.preventExtensions() is a method in JavaScript that
prevents new properties from being added to an object.
123. However, it does not prevent modifying or deleting existing
properties.
124. Syntax:- Object.preventExtensions(obj)
125. obj: The object you want to make non-extensible.
126. Returns: The same object with extensions disabled.
127. E.g: -
const car = { brand: 'Toyota' };
// Prevent adding new properties
Object.preventExtensions(car);
car.model = 'Corolla'; // ❌ Cannot add new property (Ignored in
strict mode, fails silently otherwise)
console.log(car.model); // undefined
car.brand = 'Honda'; // ✅ Can modify existing properties
console.log(car.brand); // 'Honda'
delete car.brand; // ✅ Can delete existing properties
console.log(car.brand); // undefined
How to Check if an Object is Non-Extensible :
128. Syntax :- Object.isExtensible(obj);
129. E.g :-
console.log(Object.isExtensible(car)); // false
b) Object.seal() :-
130. Object.seal() is a method in JavaScript that prevents adding
or removing properties from an object, but still allows modifying
the existing properties.
131. Syntax:- Object.seal(obj)
132. obj: The object you want to seal.
133. Returns: The sealed object.
134. E.g: -
const user = { name: 'Alice', age: 30 };
// Seal the object
Object.seal(user);
user.city = 'New York'; // ❌ Cannot add new properties
console.log(user.city); // undefined
delete user.age; // ❌ Cannot delete properties
console.log(user.age); // 30
user.name = 'Bob'; // ✅ Can modify existing properties
console.log(user.name); // 'Bob'
// Trying to change descriptor properties
Object.defineProperty(user, 'age', { writable: false }); // ❌ Error in
strict mode
How to Check if an Object is Sealed :
135. Syntax :- Object.isSealed(obj);
136. E.g :-
console.log(Object.isSealed(user)); // true
c) Object.freeze() :-
137. Object.freeze() is a method in JavaScript that prevents
adding, deleting, or modifying properties in an object. It makes
the object completely immutable.
138. Syntax:- Object.freeze(obj)
139. obj: The object you want to seal.
140. Returns: The frozen object.
141. E.g: -
const person = { name: 'Alice', age: 25 };
// Freeze the object
Object.freeze(person);
person.city = 'New York'; // ❌ Cannot add new properties
console.log(person.city); // undefined
delete person.age; // ❌ Cannot delete properties
console.log(person.age); // 25
person.name = 'Bob'; // ❌ Cannot modify properties
console.log(person.name); // 'Alice'
// Changing descriptors will fail
Object.defineProperty(person, 'age', { writable: false }); // ❌ Error in
strict mode
How to Check if an Object is Frozen:
142. Syntax :- Object.isFrozen(obj);
143. E.g :-
console.log(Object.isFrozen(person)); // true
Important Note:
144. Object.freeze() is shallow, meaning nested objects can still
be modified.
145. E.g:- Shallow Freeze:
const obj = { details: { city: 'Paris' } };
Object.freeze(obj);
obj.details.city = 'London'; // ✅ Nested object properties can still
change
console.log(obj.details.city); // 'London'
146. To deeply freeze an object, you can use recursion:
function deepFreeze(obj) {
Object.freeze(obj);
Object.values(obj).forEach(value => {
if (value && typeof value === 'object') {
deepFreeze(value);
});
const data = { user: { name: 'John', age: 30 } };
deepFreeze(data);
data.user.name = 'Jane'; // ❌ No change allowed
console.log(data.user.name); // 'John'