Difference Between __proto__
and .prototype
Properties in JavaScript
Prototypes in JS are pretty confusing. I think it helps to start at a high level. This can be an involved topic but I'll try to keep things succinct.
Understanding __proto__
Property
In JavaScript, every object has something called a "prototype". This is essentially a blueprint for the object, dictating what properties and methods it inherits from another object.
__proto__
is a special property that allows access to an object's prototype. The __proto__
property provides a way to traverse this prototype chain.
For example, consider the toString()
method. It's available in almost all objects in JavaScript. However, when you create a new object like let obj = {}
, it doesn't directly get its own toString()
method. Instead, it inherits it from its prototype.
let obj = {}; console.log(obj.toString()); // [object Object] console.log(obj.hasOwnProperty("toString")); // false
To truly understand where toString()
is defined for an object, we can use __proto__
:
let objPrototype = obj.__proto__; console.log(objPrototype.hasOwnProperty("toString")); // true
Here, we're able to confirm that toString()
is indeed defined in the prototype of obj
.
But be cautious with __proto__
, as it's considered deprecated in favor of the Object.getPrototypeOf()
and Object.setPrototypeOf()
methods, which provide more reliable and standardized ways to access and modify prototypes:
let obj = {}; let objPrototype = Object.getPrototypeOf(obj); console.log(objPrototype.hasOwnProperty("toString")); // true
So, it's best to avoid using __proto__
for modern code.
Understanding the prototype
Property
The prototype
property is specific to constructor functions in JavaScript. It doesn't represent the prototype of the constructors themselves, but rather the prototype of the object instances they create.
function Func() {} console.log(typeof Func.prototype); // object let fnObj = new Func(); console.log(Object.getPrototypeOf(fnObj) === Func.prototype); // true
The same holds true for classes:
class Clas {} console.log(typeof Clas.prototype); // object let csObj = new Clas(); console.log(Object.getPrototypeOf(csObj) === Clas.prototype); // true
Even built-in types utilize prototype properties for inheritance. For instance, when you create a regular object with {}
, it inherits from the Object
type, meaning its prototype is the same as Object.prototype
.
let obj = {}; console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
However, it's generally not recommended to modify built-in prototype objects, as this could lead to issues later on when new features are introduced.
In modern JavaScript, you typically won't need to use __proto__
or prototype
directly. If you need to access an object's prototype, use Object.getPrototypeOf()
instead of __proto__
.
Get my free, weekly JavaScript tutorials
Want to improve your JavaScript fluency?
Every week, I send a new full-length JavaScript article to thousands of developers. Learn about asynchronous programming, closures, and best practices — as well as general tips for software engineers.
Join today, and level up your JavaScript every Sunday!
Thank you, Taha, for your amazing newsletter. I’m really benefiting from the valuable insights and tips you share.