I am learning some JS and I am hoping someone can explain to me, in simplistic terms, the difference between Object.getPrototypeOf()
vs .prototype
function ParentClass() {}
function ChildClass() {}
ChildClass.prototype = new ParentClass();
var mychild = new ChildClass();
var myparent = new ParentClass();
# .getPrototypeOf
Object.getPrototypeOf(ChildClass.prototype) // ParentClass {}
Object.getPrototypeOf(mychild) // ParentClass {}
Object.getPrototypeOf(ParentClass.prototype) // {}
Object.getPrototypeOf(myparent) // ParentClass {}
# .prototype
ParentClass.prototype // ParentClass {}
myparent.prototype // undefined
ChildClass.prototype // ParentClass {}
mychild.prototype // undefined
So it looks like you can only call .prototype on a constructor?
Are there any other differences?
The prototype is an object that is associated with every functions and objects by default in JavaScript, where function's prototype property is accessible and modifiable and object's prototype property (aka attribute) is not visible. Every function includes prototype object by default.
prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype. Current standards provide an equivalent Object.
The Object. getPrototypeOf() method returns the prototype (i.e. the value of the internal [[Prototype]] property) of the specified object.
function MyConstructor() {}
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === obj.prototype // false
Object.getPrototypeOf(obj) === MyConstructor.prototype // true
MyConstructor.prototype // MyConstructor {}
obj.prototype // undefined
MyConstructor.prototype.constructor === MyConstructor // true
Object.getPrototypeOf(MyConstructor) === Function.prototype // true
The confusing part about prototypes in javascript is that there are 2 different things that sound very similar.
When you create a new object, if the function or object used to create the new object has a .prototype method, then the object referenced by .prototype
will become the new object's prototype newObj.__proto__
.
Sounds complicated... let's break it down further.
Example - Using a function as a constructor
When you use the new
keyword on a function (i.e. you use the function as a constructor) then the function's .prototype becomes the new obj.__proto__
.
Lets first make a function and checkout this .prototype property
function MyConstructor(){
}
console.log(MyConstructor.prototype) // {}
Wait up... MyConstructor.prototype // {}
- did something magically happen? Where did this empty object {}
come from?
2 things here:
Javascript automatically creates a .prototype object whenever you declare a function - automagically.
This object is not empty. It actually has a property that points back to the function that created the object (the object's 'constructor'). Let's check it out:
console.log(MyConstructor.prototype.constructor); // [Function: MyConstructor]
MyConstructor.prototype.constructor === MyConstructor // true
So for functions, the .prototype property and it's associated object are created automatically.
Still confused? Lets add some methods in there to make it easier to see what's going on...
function MyConstructor(){
}
MyConstructor.prototype.func2 = function(){
};
console.log(MyConstructor); // [Function: MyConstructor]
console.log(MyConstructor.prototype); // MyConstructor { func2: [Function] }
MyConstructor.func2(); // TypeError: MyConstructor.func2 is not a function
Clearly we can see from the above code that MyConstructor and MyConstructor.prototype are 2 separate entities.
An object's prototype (not .prototype - see A. above) is what javascript uses to lookup and resolve methods that aren't already in the object (more on this later).
Continuing on from above, when we create an object from a function or object that has a .prototype property, the newly created object will have it's object.__proto__
referencing this .prototype object.
An object's prototype can be accessed by
Object.getPrototypeOf(obj)
or the deprecated
obj.__proto__
Example - Using a function as a constructor
Lets make a new object using the function MyConstructor as a constructor.
function MyConstructor(){
}
var obj = new MyConstructor()
console.log(Object.getPrototypeOf(obj)); // {}
Here are the three relevant things:
obj.__proto__
--> MyConstructor.prototypeSo obj.__proto__
is MyConstructor.prototype
. Here is the proof:
MyConstructor.prototype === Object.getPrototypeOf(obj) // true
Lets add a method to MyConstructor
function MyConstructor(){
this.func1 = function(){
console.log("this is func1");
};
}
var obj = new MyConstructor();
obj.func1(); // this is func1
From the above you can see that you can call methods that were declared in the constructor. In fact, if we have a look, our declared method func1 is actually part of obj due to the way javascript creates objects.
console.log(obj); // MyConstructor { func1: [Function] }
We can also add methods that obj can use by adding the methods to the prototype. e.g.
MyConstructor.prototype.func2 = function(){
console.log("this is func2");
};
obj.func2(); // this is func2
MyConstructor and MyConstructor.prototype methods will be available to all objects created using MyConstructor using this setup.
Useful References
Definitive Guide to Object-Oriented JavaScript
Understanding JavaScript: Inheritance and the prototype chain
A Plain English Guide to JavaScript Prototypes
@lukeaus's answer is excellent. For me the most important points are:
function MyConstructor() {} // automatically creates MyConstructor.prototype
// You can add methods to MyConstructor.prototype for objects to "inherit"
MyConstructor.prototype.foo = function() { console.log("do foo") }
// Or even reassign .prototype
// MyConstructor.prototype = { foo: function() { console.log("more foo?") } }
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === MyConstructor.prototype // true
obj.foo()
So obj's prototype is MyConstructor.prototype. What's MyConstructor's prototype? Well, every function "inherits" from Function, so Object.getPrototypeOf(MyConstructor) === Function.prototype
As a side note, things get weird if you assign .prototype to something silly like:
function MyConstructor() {}
MyConstructor.prototype = "foo" // make objects inherit from... a string?
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === MyConstructor.prototype // false!
Object.getPrototypeOf()
vs .prototype
Prototype
: Every object in javascript has a prototype. This is simply another object from which it 'inherits' properties and methods. This concept is called prototypal inheritance and is the only form of inheritance which exist in javascript. Constructs such as the class
keyword in javascript is merely syntactic sugar built on top of this prototypal inheritance system.
Every function has a prototype
object property. When this function is then used as a constructor function with the new
keyword the newly created object will inherit from this prototype
object.
Object.getPrototypeOf()
: Is a function which return a reference of this prototype object. We pass in an object as an argument and it will return the prototype object reference.
function Dog (name) {
this.name = name;
}
// We can put properties on the prototype of the Dog constructor
Dog.prototype.bark = function () { console.log('woof'); };
let dog = new Dog('fluffie');
// Our newly created dog now has access to this bark method via the prototype chain
dog.bark();
// With the Object.getPrototypeOf method the Dog prototype object is returned
console.log(Object.getPrototypeOf(dog));
Prototypal inheritance uses a prototype chain is a very powerful concept. It bascially works in the following manner:
prototype
of the object. prototype
it will climb up the prototype chain and look in the prototype
of the objects prototype
object. This will repeat untill there is no more higher chain in the prototype chain (i.e. no higher object to inherit from).This enables the following advantages:
Object.prototype
and Array.prototype
are many functions which provides us a lot of functionality. For example, we can use the functions of Array.prototype
on any array via prototypal inheritance.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With