Object-Oriented JavaScript: SDE-3 Reference
This section details prototypal inheritance, execution contexts, constructor mechanics, and memory allocation patterns for objects.
15. Factories and Classes
JavaScript supports two primary patterns for object creation: Factory Functions and ES6 Classes.
Factory Functions (Closure State)
Factory functions construct and return a new object literal. They achieve state privacy by wrapping fields inside closures.
- Pros: Clear encapsulation (no
thiscontext binding issues, private variables cannot be leaked). - Cons: High memory footprint. If you create 1,000 instances, 1,000 separate copies of each method are allocated in memory.
function UserFactory(name) {
let _name = name; // Private state via closure
return {
getName: () => _name,
setName: (val) => { _name = val; }
};
}ES6 Classes (Prototype Shared State)
ES6 Classes are syntactic sugar over prototype chains.
- Pros: Memory efficient. Methods are attached to the prototype once and shared across all instances.
- Cons: Relies on dynamic execution context (
this), which can lose binding during event callbacks.
class UserClass {
#name; // Native private class field (ES2020)
constructor(name) {
this.#name = name;
}
getName() {
return this.#name; // Shared prototype method
}
}16. this, call, apply and bind
The this keyword refers to the execution context of the current scope. Its value is not static; it is determined at runtime based on how a function is invoked.
The Five Binding Rules
- Default Binding: If a function is called standalone (e.g.
fn()),thisresolves to the global object (windowin browsers,globalin Node). In strict mode ("use strict"), it resolves toundefined. - Implicit Binding: If a function is called as an object method (e.g.
obj.method()),thisresolves to the containing objectobj. - Explicit Binding: Using
.call(),.apply(), or.bind()to forcethisto point to a specific object. newBinding: When called withnew, the function acts as a constructor, andthisresolves to the newly created instance.- Lexical Binding (Arrow Functions): Arrow functions do not define their own
this. They capture thethisvalue of their enclosing lexical context at creation time.
const obj = {
name: "Target Object",
printImplicit() {
console.log(this.name);
},
printLexical: () => {
console.log(this.name); // Arrow function: 'this' is outer global context -> undefined
}
};call vs. apply vs. bind
call(thisArg, arg1, arg2, ...): Invokes the function immediately, passing arguments individually.apply(thisArg, [arg1, arg2, ...]): Invokes the function immediately, passing arguments as an array.bind(thisArg, arg1, ...): Returns a new bound function with its context permanently locked, but does not execute it.
function greet(salutation, punctuation) {
return `${salutation}, my name is ${this.name}${punctuation}`;
}
const person = { name: "Antigravity" };
// Explicit Invocation
console.log(greet.call(person, "Hello", "!")); // "Hello, my name is Antigravity!"
console.log(greet.apply(person, ["Hello", "!"])); // "Hello, my name is Antigravity!"
// Context Binding
const boundGreet = greet.bind(person, "Welcome");
console.log(boundGreet(".")); // "Welcome, my name is Antigravity."17. new, Constructor, instanceof and Instances
When the new operator is executed on a function, the engine performs the following 4 steps under the hood:
- Creates a new empty object in the heap:
{}. - Links prototypes: Sets the new object's internal prototype (
[[Prototype]]or__proto__) to point to the constructor function'sprototypeobject. - Binds
this: Invokes the constructor function with the newly created object bound tothis, allocating internal instance properties. - Returns the object: If the constructor returns an object explicitly, that object is returned. Otherwise, the newly created object is returned.
function Person(name) {
this.name = name;
}
// Emulating 'new' behavior
function customNew(Constructor, ...args) {
const instance = Object.create(Constructor.prototype); // Steps 1 & 2
const result = Constructor.apply(instance, args); // Step 3
return (typeof result === 'object' && result !== null) ? result : instance; // Step 4
}The instanceof Operator
instanceof checks if the prototype object of a constructor appears anywhere in the prototype chain of an object.
// prototype chain walk: instance.__proto__ === Constructor.prototype ?
console.log(new Person("A") instanceof Person); // true18. Prototype Inheritance and Prototype Chain
Unlike classical class-based languages (Java, C++), JavaScript uses Prototypal Inheritance.
Prototype Chain Delegation
When accessing a property on an object (e.g. obj.prop), the engine checks:
- Does
objhavepropas an own property? If yes, return it. - If not, lookup the internal
[[Prototype]]link toobj.__proto__and check if it exists there. - Traverse up the prototype chain recursively.
- If it reaches
Object.prototype.__proto__(which points tonull), returnundefined.
const base = { greeting: "Hello" };
const derived = Object.create(base); // derived delegates to base
derived.name = "Instance"; // Shadowing property: added directly to derived
console.log(derived.name); // "Instance" (found on self)
console.log(derived.greeting); // "Hello" (delegated up the prototype chain to base)19. Object.create vs Object.assign
These two operations differ in how they structure prototype linkages.
Object.create(proto, propertiesObject): Creates a brand-new empty object and sets its prototype (__proto__) to point directly toproto.Object.assign(target, ...sources): Performs a shallow copy of all enumerable, own properties from one or more source objects to atargetobject. It triggers getters on source objects and setters on the target object. It does not link prototypes.
const parent = { family: "Developer" };
// Object.create
const child1 = Object.create(parent);
console.log(Object.getPrototypeOf(child1) === parent); // true (Linked prototype)
// Object.assign
const child2 = Object.assign({}, parent);
console.log(Object.getPrototypeOf(child2) === parent); // false (Cloned property, prototype is Object.prototype)Mark this page when you finish learning it.
Spotted something unclear or wrong on this page?