In JavaScript, every object has an internal property called [[Prototype]] that points to another object. This link is what allows objects to inherit properties and methods.
Functions also have a public prototype property. When you use the new keyword, the newly created object’s [[Prototype]] is set to that function’s prototype object.
Together, [[Prototype]], the prototype property, and the prototype chain form the core of JavaScript’s object system.
[[Prototype]]: A hidden internal link from one object to another.prototype on functions: The object that instances created by new will inherit from.__proto__: A legacy accessor on objects that exposes their [[Prototype]].Object.create(): A method to create a new object with a specified prototype.Array.prototype, Date.prototype, etc.You can inspect an object’s prototype using Object.getPrototypeOf() or the legacy __proto__ accessor:
When you access a property on an object, JavaScript:
[[Prototype]].null (end of the prototype chain).Constructor functions use their prototype object as the shared place for methods. Objects created with new will delegate to that prototype for method lookups.
Person objects share sayHi()).Object.create().
const obj = {};
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
const parent = {
greet() {
console.log("Hello");
}
};
const child = Object.create(parent);
child.greet(); // "Hello" (inherited from parent)
function Person(name) {
this.name = name;
}
// Shared method for all Person instances
Person.prototype.sayHi = function() {
console.log("Hi, I'm " + this.name);
};
const user = new Person("Alice");
user.sayHi(); // Hi, I'm Alice
const animal = { sound: "Generic" };
const dog = Object.create(animal);
// Own property shadows the prototype property
dog.sound = "Bark";
console.log(dog.sound); // "Bark" (own property)
console.log(animal.sound); // "Generic" (unchanged)
prototype vs __proto__
function Car() {}
const car = new Car();
// car.[[Prototype]] === Car.prototype
console.log(car.__proto__ === Car.prototype); // true
const base = { type: "base" };
const derived = Object.create(base);
console.log(derived.type); // "base"
console.log(Object.getPrototypeOf(derived) === base); // true
const arr = [1, 2, 3];
// arr.[[Prototype]] is Array.prototype in most environments
console.log(arr.__proto__ === Array.prototype); // true
// You can use built-in methods from the prototype
console.log(arr.map((x) => x * 2)); // [2, 4, 6]
Consider this code:
const parent = { greet() { console.log("Hello"); } };
const child = Object.create(parent);
child.greet();
Step by step:
child does not have its own greet property.child.[[Prototype]], which points to parent.greet on parent and calls it.Hello.This is the prototype chain in action: child → parent → Object.prototype → null.
Object.create() when you want fine-grained control over an object’s prototype.Function.prototype (like Person.prototype.sayHi) instead of inside the constructor.Array.prototype) in real projects.prototype (on functions) and __proto__ (on objects).Object.getPrototypeOf() over __proto__ in modern code.Book with a prototype method describe() that logs "Title by Author".Object.create() to create an object that inherits from another and test property lookup on both the child and parent.sound or type) on the child object and observe how shadowing works.Object.getPrototypeOf() and draw the prototype chain you see in the console.class syntax and relate it back to prototypes.