prototype Property vs [[Prototype]]

A function's `prototype` property is the object that instances created with `new` can inherit from, while an object's internal `[[Prototype]]` is the object used for its property lookup chain. They are related, but they belong to different things and serve different roles.

In JavaScript, every ordinary object has an internal `[[Prototype]]` reference. When a property is not found directly on the object, JavaScript can continue looking through this prototype chain. `Object.getPrototypeOf(obj)` exposes the value of that internal relationship.

Constructor functions have a `prototype` property. This property normally points to an object that becomes the `[[Prototype]]` of objects created with `new Constructor()`. Methods placed on that object can therefore be shared by all such instances.

For example, if `Person.prototype.sayHi` exists, an instance created with `new Person()` does not need its own `sayHi` property. Property lookup can find the method through the instance's `[[Prototype]]`, which points to `Person.prototype`.

The expression `obj.__proto__` is commonly used as an accessor for an object's prototype, but it is a legacy accessor and should generally not be preferred in new code. Use `Object.getPrototypeOf(obj)` to read the prototype and `Object.setPrototypeOf(obj, proto)` when changing it is genuinely necessary.

Classes use the same underlying prototype mechanism. A class's instance methods are placed on its `prototype` object, while each instance has a `[[Prototype]]` pointing to that object. Thus, classes provide different syntax over JavaScript's prototype-based inheritance model.

Key points

Interview questions

What is the difference between a function's `prototype` property and an object's `[[Prototype]]`?

A function's `prototype` property is an object intended to be used as the prototype of instances created by that function with `new`. An object's `[[Prototype]]` is the internal link to another object used during property lookup. For `const x = new Foo()`, the usual relationship is `Object.getPrototypeOf(x) === Foo.prototype`. So one is an ordinary property on the constructor function, while the other is an inheritance relationship on the instance.

What happens when you run `new Person()`?

The `new` operation creates a new object and establishes its prototype relationship using `Person.prototype`. The constructor function then executes with the new object as its `this` value. If the constructor returns an ordinary object explicitly, that returned object can replace the newly created one; otherwise the created instance is returned. This is why `Object.getPrototypeOf(instance) === Person.prototype` is normally true.

Where should you put a method that should be shared by all instances?

For constructor-function code, put the method on the constructor's `prototype` object. Instances can then find the method through their `[[Prototype]]` chain instead of each storing a separate function. This reduces repeated function objects and makes the shared behavior accessible to all instances. Class methods use this same prototype-based arrangement.

Why does `obj.hasOwnProperty('x')` differ from checking whether `obj.x` exists?

Property access such as `obj.x` searches the object and then its prototype chain, so an inherited property can be returned. An own-property check only considers properties directly stored on the object itself. Therefore an object can successfully access a method inherited from its prototype while not owning that method. Modern code can use `Object.hasOwn(obj, 'x')` for a direct own-property check.

How do JavaScript classes relate to prototypes?

Classes do not replace the prototype mechanism; they provide syntax for working with it. Instance methods declared in a class are placed on the class's `prototype` object. Instances created by the class have that prototype in their `[[Prototype]]` chain. This allows methods to be shared rather than duplicated on every instance.