Object Fundamentals and DeepDive

An object is a non-primitive data type.
While a
stringis just a value, anObjectis a reference to a memory location containing key-value pairs.
# Creating the Entity with Features (Object Creation)
Object Literal:
const obj = {}(Fastest, most common).Constructor:
new Object()(Our code:const o = new Object({})) , mostly same as Literal, but literal obj creation is Faster.Object.create(): Creates a new object using an existing object as a prototype.
# Accessing & Updating
Dot Notation:
o2.name(Simple, clean).Bracket Notation:
o2["name"](Powerful; allows using variables as keys).
const person = {
isHuman: false,
printIntroduction() {
console.log(`Am I human? ${this.isHuman} `)
console.log(`Am I human? ${this["isHuman"]}`)
}
}
const me = Object.create(person) )
- Factory Functions: Functions that
returnan object. Great for creating many similar objects withoutnew.
function createPerson(name, age) {
return {
name: name,
age: age,
greet() {
console.log(`Hello, my name is \({this.name} and I am \){this.age} years old.`);
}
};
}
// Creating objects using the factory function
const person1 = createPerson('Leo', 23);
const person2 = createPerson('Anup', 24);
person1.greet(); // Out: Hello, my name is Leo and I am 23 years old.
person2.greet(); // Out: Hello, my name is Anup and I am 24 years old.
- Constructor Functions: Uses
thisandnew.
function Person(first, last)
{
this.firstName = first; // 'this' refers to the new instance
this.lastName = last;
this.sayName = function() {
console.log(this.firstName + " " + this.lastName);
};
}
// Creating new instances using the 'new' keyword
const jay= new Person("Jay", "Ahirrao");
jay.sayName(); // Output: Jay Ahirrao
What
newDoes Behind the Scenes:
Creates a new empty object:
{}.Binds
thisto that new object.Sets the new object's internal
__proto__property to the constructor's (function's)prototype.Executes the constructor function code.
Returns the object automatically (if no explicit object is returned).
Classes: ES6 "Syntactic Sugar" for Constructor Functions.
Accessing the Systems
Dot Notation (
obj.prop): Used when we know the key name.Bracket Notation (
obj["prop"]): Mandatory if the key has spaces, starts with a number, or is stored in a variable (e.g.,obj[keyName]).
2. Security Protocols: Mutability Control
JavaScript objects are "mutable" by default (we can change them).
Our code explored the three levels of "Locking" an object.
Object.preventExtensions(obj): (Level 1) We can't add new properties. We can delete or change existing ones.Object.seal(obj): (Level 2) We can't add or delete properties. We can change existing values.const o3 = { name: "bijoy", age:47 } console.log(o3); Object.seal(o3) o3.name = "joy"; o3.gorapan = 100 // not error console.log(o3);- In our code:
o3.name= "joy"worked because it was an update, buto3.gorapanfailed because it was an addition.
- In our code:
Object.freeze(obj): (Level 3) The "Ultimate Lock." No additions, no deletions, no updates.const o2 = { name: "Narayan", stealth:54 } console.log(o2); Object.freeze(o2) o2.name = "Jay"; o2.strength = 99; // not error console.log(o2);- In our code:
o2.name= "Jay"failed silently (or throws an error in strict mode).
- In our code:
3. The Classified Files: Property Descriptors
Every property in an object has "meta-data" called Attributes. We accessed these via Object.defineProperty.
const sec = { name: "diamond" }
Object.defineProperty(sec, "MRP",
{
value: 78_00_000,
writable: false,
enumerable: false,
configurable:false
})
console.log(sec.MRP);
sec.MRP = 58_00_000
console.log(sec.MRP); // value gets changed
for(const [k,v] of Object.entries(sec)){
console.log(\({k} : \){v});
}
console.log(Object.getOwnPropertyDescriptor(sec, "MRP")); console.log(Object.getOwnPropertyDescriptor(sec, "name"));
value: The actual data.writable: Iffalse, the value cannot be changed.enumerable: Iffalse, the property is invisible to loops (for...in) andObject.keys().- Note: Here,
MRPwas hidden because we set this tofalse.
- Note: Here,
configurable: Iffalse, we cannot delete the property or change these attributes again.
4. Navigation Systems : Iteration (Looping)
How do we walk through a jet's inventory?
Object.keys(obj): Returns an array of keys.Object.values(obj): Returns an array of values.Object.entries(obj): Returns an array of[key, value]pairs. (Used in ourfor...ofloop).for...inloop: Iterates over all enumerable properties, including those in the prototype chain.
5. The "This" Radar : Execution Context
This is the most complex system. this is a pointer to the owner of the current code execution.
const go = {
sname: "jay",
wins: 49,
loss: 0,
belts: ["global champion", "undisputed", "uncrowned"],
introduce() {
console.log(\({this.sname} has \){this.wins} wins & ${this.loss} losses);
this.belts.forEach((element, idx) => {
console.log(belt no \({idx + 1} : \){element} );
});
}
}
go.introduce();
Global Context: In the open air (global),
thisis thewindow(orglobalin Node).Function Context:
Simple Call:
func()->thisis Global/Undefined.Method Call:
obj.method()->thisisobj.
Arrow Functions: As we've seen in our Arrow Function Blog ... They do not have a
this. They use Lexical Scoping , meaning they look at their parent'sthisat the moment they are defined.- In our
go.introduce()code: TheforEacharrow function successfully uses thethisfromintroduceto seethis.sname. If that was a regular function,this.snamewould beundefined.
- In our
6. The Blueprint: Prototype vs. Class
When building a fleet of jets, we don't want to waste memory.
The Prototype Chain
Every object has a hidden link ([[Prototype]]) to another object. If we look for a property on d1 and it’s not there, JS looks at myCar.prototype.
Memory Efficiency: Methods added to the
.prototype(like ourgetDetails) are stored once in memory.Instance Methods: Methods defined inside the constructor (like our
myCar2) are duplicated for every single instance created. Don't do this for large apps!
//TIP : A 'regular nested function & a normal arrow function' doesnt inherit "this"
// but nested arrow function does
// constructor function
function myCar(name, age, hope) {
this.name = name;
this.age = age;
this.hope = hope;
}
myCar.prototype.getDetails = function () {
return `Oh "\({this.name}", u are hoping to get \){this.hope}, are you SANE ? No Doubt , your age is ${this.age} !`
}
const d1 = new myCar("Jay", 20, "BMW")
const d2 = new myCar("Jay", 20, "Range Rover")
console.log(d1.getDetails());
Classes
class is the modern way to write prototypes.
Constructor: Runs once when we use
new.Methods: Automatically added to the prototype.
Instance Properties: Properties like
this.nameare unique to each object.
class Cricketer {
constructor(name, role) {
this.name = name
this.role = role
this.jerseyno = undefined
this.undefined = null // beacomes this."undefined" as in prope name
}
introduce(){
console.log(`\({this.name} is \){this.role} and \({this.jerseyno} with \){this.undefined}`);
}
}
7. Memory Management: Factory vs. Constructor
Factory Functions: Clean, no
thisheadaches, but every object carries its own methods (higher memory).Constructor/Classes: More technical, uses
thisandprototype, but extremely memory-efficient for thousands of objects.
Common Consfusion about - key style , and new vs { } creation
const obj1 = new Object(
{
name: String,
inter(){ console.log(`this is \({this.name} \){this["name"]}`); }
})
const obj2 = new Object(
{
"name": "JAy",
inter(){ console.log(`this is \({this.name} \){this["name"]}`);}
})
const obj3 = new Object(
{
name: "JAy",
inter(){ console.log(`this is \({this.name} \){this["name"]}`);}
})
const o2 = { name: "Narayan", stealth:54 }
obj1: Thenameproperty is set to theStringconstructor function itself, not a string value. Callingobj1.inter()would print:"this is function String() { [native code] } function String() { [native code] }"[2].obj2andobj3: These are functionally identical. In JavaScript,nameand"name"as keys are treated the same [1]. Callinginter()on either will print:"this is JAy JAy".o2: This is a standard object literal. It’s the most common and concise way to create an object compared to thenew Object()syntax used above [1].
