JavaScript Prototype Chain and Inheritance
Understanding JavaScript's prototype-based inheritance system
JavaScript Prototype Chain and Inheritance
1. Prototypes in JavaScript
Definition
- In JavaScript, every object has an internal link to another object called its prototype.
- Properties and methods defined on the prototype are shared across all instances created from the same constructor.
- This mechanism enables prototype-based inheritance.
Function Constructors and prototype
-
Functions in JavaScript are special objects.
-
Every function has a
prototype
property by default. -
When used with the
new
operator, thisprototype
object becomes the prototype of the newly created instance. -
Example:
function Person(name) { this.name = name; } Person.prototype.sayHello = function () { console.log(`Hi, I'm ${this.name}`); }; const hank = new Person("Hank"); hank.sayHello(); // "Hi, I'm Hank"
-
Here,
sayHello
is not copied to each instance; instead, instances referencePerson.prototype
through their internal__proto__
.
The new
Operator
When a function is called with new
, the following steps happen:
- A new empty object is created.
- The object’s internal
__proto__
is set to the function’sprototype
. - The constructor function is executed, binding
this
to the new object. - If no other object is explicitly returned, the new object is returned.
function Person(name) {
this.name = name;
}
const p1 = Person("Hank"); // Without `new`
// `this` refers to global object → global.name = "Hank"
console.log(p1); // undefined
const p2 = new Person("Hank"); // With `new`
// A new Person object is created
console.log(p2); // Person { name: "Hank" }
Prototype Chain
-
If a property is not found on an object, JavaScript follows the
__proto__
link to search its prototype. -
This continues up the chain until it reaches
Object.prototype
, the root of all objects. -
Example:
function Person(name) { this.name = name; } Person.prototype.lastname = "Kim"; const hank = new Person("Hank"); console.log(hank.lastname); // "Kim"
- The property
lastname
is not defined directly onhank
. - The engine looks into
hank.__proto__
→ finds it inPerson.prototype
.
- The property
-
Built-in objects also rely on prototypes:
const arr = [3, 1, 2]; arr.sort(); // Works because Array.prototype defines sort()
Extending Prototypes
-
Developers can extend native prototypes to add custom behavior:
Array.prototype.myMethod = function () { return "Custom method for all arrays!"; }; const arr = [1, 2, 3]; console.log(arr.myMethod()); // "Custom method for all arrays!"
-
Caution: modifying built-in prototypes can cause conflicts and is discouraged in production.
ES6 Classes and Prototypes
- Classes (introduced in ES6) are syntactic sugar over prototype-based inheritance.
- Class methods are placed on the constructor’s
prototype
just like with function constructors. -
Example:
class Person { constructor(name) { this.name = name; } sayHello() { console.log(`Hi, I'm ${this.name}`); } } console.log(Person.prototype); // { constructor: ƒ Person, sayHello: ƒ }
2. Functions and Objects in JavaScript
Primitive Types vs Objects
- Primitive types:
string
,number
,boolean
,null
,undefined
,symbol
. - Everything else is an object: arrays, functions, maps, sets, etc.
Arrays Are Objects
-
Arrays are special objects with integer-like keys and a
length
property:const arr = [1, 2, 3]; console.log(typeof arr); // "object" console.log(arr.length); // 3 console.log(arr[0]); // 1
-
Internally similar to:
{ "0": 1, "1": 2, "2": 3, length: 3 }
-
Arrays are iterable because they implement the iterator protocol.
Functions Are Objects
-
Functions are callable objects:
- They are objects and can have properties.
- They also have an internal
[[Call]]
slot that makes them executable.
function sayHello() { console.log("hi"); } console.log(typeof sayHello); // "function" sayHello.foo = 123; console.log(sayHello.foo); // 123
-
Functions are treated specially by
typeof
(returns"function"
) but are still objects under the hood.
3. Summary
- Prototype: Objects inherit from other objects through the prototype chain. Function constructors define methods on their
prototype
, shared across instances. new
operator: Automates object creation, prototype linkage, andthis
binding.- Prototype chain: Property lookup walks up
__proto__
untilObject.prototype
. - Classes: Syntax sugar for prototype-based inheritance, not a new mechanism.
- Everything but primitives is an object: Arrays and functions are just special types of objects.
- Functions are objects: Can hold properties like objects, but also executable due to
[[Call]]
.