JavaScript Advanced (I) - Prototype to Prototype Chain
In the world of JavaScript
, we often create an instance object through constructors:
function Person(name) {
this.name = name
}
const person = new Person('Mark')
console.log(person.name) // Mark
We use the constructor Person
to create an instance object person
with new
.
On the instance object person
, there is a private property __proto__
that points to the prototype object prototype
of its constructor,
So, what is prototype
, what is __proto__
?
Next, we start to get to the point.
prototype
In JavaScript, each function has a prototype
property that points to the prototype object of the function.
function Person(name) {
this.name = name
}
Person.prototype.age = 18
const person1 = new Person('Mark')
const person2 = new Person('John')
console.log(person1.name, person1.age) // Mark 18
console.log(person2.name, person2.age) // John 18
As you can see, when both person1
and person2
print the age
attribute value is 18
.
This is because Person.prototype
is exactly the prototype of the instance objects person1
and person2
.
Since prototype
points to a prototype, then, what is prototype?
To a simple understanding, in JavaScript
, when each object is created, there is another object associated with it, and this associated object refers to the prototype.
Warning
null
has no prototype.
Objects inherit ** attributes from their prototype objects. This is why both person1
and person2
print the age
attribute value is 18
.
__proto__
In JavaScript
, each object (except null
) has a private property __proto__
, This property points to the prototype of the object's constructor.
function Person(name) {
this.name = name
}
const person = new Person('Mark')
console.log(person.__proto__ === Person.prototype) // true
At this point, you will find that since the constructor has a prototype prototype
, the prototype is also an object, and the object has a prototype object that points to its constructor. So does the prototype object of the constructor also have its prototype object?
constructor
Before explaining the prototype, you need to understand a property on the prototype constructor
, which points to the constructor associated with the prototype object:
function Person(name) {
this.name = name
}
const person = new Person('Mark')
console.log(person.prototype.constructor === Person) // true
It helps us understand the constructor of the prototype.
Prototype of prototype
When we print and output Person.prototype.__proto__
in the console, we find that an object is printed:
function Person(name) {
this.name = name
}
console.log(Person.prototype.__proto__)
output
:
Since the prototype of Person
also has a prototype, what is the constructor of the prototype object of this prototype?
We can use constructor
to get its constructor:
function Person(name) {
this.name = name
}
console.log(Person.prototype.__proto__.constructor)
output
:
You can find the prototype object of the prototype object of Person
, and the constructor pointed to is Object
.
That is, the prototype of Person.prototype
points to Object.prototype
.
So, does Object.prototype
have its own prototype?
It can be found that the prototype of Object.prototype
points to null
.
And null
means no object, it has no prototype.
Prototype Chain
Person.prototype
-> Object.prototype
-> null
(Consequently via __proto__
)
This kind of object has a prototype object, and its prototype object has its prototype object, layer by layer, like a chain, and is called Prototype chain
.
Almost all objects in JavaScript are instances of Object at the top of the prototype chain.
Tips
__proto__
is a non-standard attribute, but most browsers support accessing prototypes through this attribute.
__proto__
is an getter/setter
accessor on Object
in implementation. When using obj.__proto__
, it can be understood that Object.getPrototypeOf(obj)
is returned.
Inheritance based on prototype chain
The JavaScript
object is a dynamic property "package" (referring to its own properties). The JavaScript
object has a chain pointing to a prototype object. When trying to access an object's properties, it not only searches on the object, but also searches for the object's prototype and the prototype of the object's prototype, searching up layer by layer until it finds an attribute with a matching name or reaches the end of the prototype chain.
function Person(name) {
this.name = name
}
Person.prototype.age = 18
const person1 = new Person('Mark')
const person2 = new Person('John')
console.log(person1.name, person1.age) // Mark 18
console.log(person2.name, person2.age) // John 18
In this example, although the instance object of Person
does not have the age
attribute itself, because its prototype object has the age
attribute, The instance object inherits the attribute age
from its prototype object. Therefore, the value of its age
property is 18
.