On the prototype and prototype chain of JavaScript
Here, we list several concepts of prototypes, as follows:
- Prototype property
- [[prototype]]
__proto__
Prototype property
Whenever a function is created, a property is created for the function prototype
that points to the prototype object of the function. The instance object does not own the property.
By default, it 原型对象
also gets a property that constructor
contains a pointer to prototype
the function where the property resides.
Person.prototype.constructor===Person
[[prototype]] and
__proto__
In JavaScript, internal properties that are not accessible are represented in [[propertyName]]
this form, such as the enumeration property [[Enumberable]].
[[prototype]]
A property can only be a property that an object may have. For example, an instantiated object and 原型对象
, rather than a constructor. This property points to the prototype object for the constructor of the object that owns the property. Note that 构造函数
this refers to the constructor that uses new
the method. It is not changed because the properties on the prototype object have changed constructor
.
__proto__
What is it, is the [[propertyName]]
realization of the right. In other words, you can access the prototype object of the object's constructor under the browser that supports the implementation (Ff,chrome,safari). Like what:
var Person=function(name){ this.name=name;};var p1=new Person();p1.__proto__===Person.prototype;//truePerson.prototype={};var p2=new Person();p2.__proto__===Object.prototype;//false
Of course, __proto__
only the browser's private implementation, the current ECMAScript standard implementation method is Object.getPrototypeOf(object)
.
var Person=function(name){ this.name=name;};var p1=new Person();Object.getPrototypeOf(p1)===Person.prototype;//truePerson.prototype={};var p2=new Person();Object.getPrototypeOf(p2)===Object.prototype;//false
Another way to judge an instance object and its prototype object is to have a pointing relationship (the prototype object that the instance's [[prototype]] points to its constructor): isPrototypeOf
. Like what:
Person.prototype.isPrototypeOf(p1);//true
Because 原型对象
it is also an object, it naturally has properties as well [[prototype]]
.
Javascript
There is no class-inheriting model, but prototype inheritance is used with prototype objects prototype
.
Although this is often seen as Javascript
a drawback, in fact, prototype inheritance is more powerful than the traditional class-inheriting model. For example, building a class model at the top of the prototype inheritance is simple, but the reverse is a much more difficult task.
Javascript
Is the only one that has been widely used as an inherited language, so it takes time to understand the differences between the two ways of inheriting.
The first major difference is the use of the Javascript
prototype chain to inherit:
function Foo() { this.value = 42;}Foo.prototype = { method: function() {}};function Bar() {}
Set the instance of the Bar
prototype
Foo
object to:
Bar.prototype = new Foo();Bar.prototype.foo = ‘Hello World‘;
Make sure that Bar
the constructor is itself, and create a new Bar
object instance:
Bar.prototype.constructor = Bar;var test = new Bar();
Let's look at the composition of the entire prototype chain:
test [instance of Bar] bar.prototype [instance of Foo] {foo: foo.prototype {method: ...} object.prototype { tostring: ... /* etc. */}
In the example above, the object test
will inherit both Bar.prototype
and Foo.prototype
. So it can access the functions defined in Foo
method
. Of course, it can also access properties value
. It should be mentioned that when new Bar()
you do not create a new Foo
instance, you reuse the instance of the prototype object itself Foo
. Similarly, all Bar
instances share the same value
property. For example, we illustrate:
test1 = new Bar(); test2 = new Bar(); Bar.prototype.value = 41; test1.value //41 test2.value//41
Prototype chain lookup mechanism
When a property of an object is accessed, the Javascript
entire prototype chain is traversed from the object itself, until the corresponding property is found. If you reach the top of the prototype chain at this point, that is Object.prototype
, the property you want to find is still not found in the example above, then the Javascript
value is returned undefined
.
Properties of the prototype object
Although the properties of the prototype object are Javascript
used to construct the prototype chain, we can still assign the value to it. But the original values are copied to prototype
be invalid, such as:
function Foo() {}Foo.prototype = 1; // no effect
Here is a digression of this article, which describes what the original value is:
In Javascript
, the variable can hold two types of values, namely the original value and the reference value.
1. Original Value (primitive value)
:
The original values are fixed and simple values, which are stack
simple data segments stored in the stack, that is, their values are stored directly in the location where the variable is accessed.
The original type has the following five types: Undefined, Null, Boolean, Number, String
.
2. Reference value (reference value)
:
Reference values are large objects that are stored in the heap, that heap
is, the value stored at the variable is a pointer pointer
to the memory of the storage object. All reference types are integrated from Object
.
Prototype chain performance issues
If the property you need to find is at the top of the prototype chain, the lookup process will undoubtedly have a negative impact on performance. This will be a key consideration in scenarios where performance requirements need to be rigorous. In addition, attempting to find a nonexistent property will traverse the entire prototype chain.
Similarly, when traversing the properties of an object, all properties on the prototype chain are accessed.
Summarize
Understanding prototype inheritance is a prerequisite for writing more complex Javascript
code, while paying attention to the height of the prototype chain in the code. Learn to split the prototype chain when faced with performance bottlenecks. In addition, to distinguish prototype objects from prototype
prototypes __proto__
, the main discussion here is that prototype
the prototype object does not elaborate on __proto__
the problem of prototypes.
Photo from Kzloser
Picture description
1. A total of three categories of objects (large blue box)
2. Instance objects (through new XX () instances), only attributes associated with the prototype chain __proto__
, pointing to their corresponding prototype objects *.prototype
.
3. constructor objects are divided into native and custom categories. There are attributes associated with the prototype chain __proto__
, in addition to the prototype
attributes. Their __proto__
properties are all pointing Function.prototype
to the prototype object. prototype
also points to the corresponding prototype object.
4. prototype Objects have __proto__
unique properties in addition to their own constructor
. Its __proto__
point is Object.prototype
that, in addition Object.prototype
to itself, it is pointing to itself null
. constructor
the properties point to their corresponding constructor object.
5. The prototype chain is based on __proto__
. An instance can constructor
access the corresponding constructor object only through its corresponding prototype object. The constructor can prototype
access the corresponding prototype object only through its corresponding function.
Prototypes and prototype chains are the most central content in JavaScript, and if they don't understand the relationship between them, then we can't understand the language.
In JS, there are two main ways to create objects, namely, object literals and calling constructors
//对象字面量var obj1 = {}//调用构造函数var obj2 = new Object()
In fact, the two methods of creating objects, essentially the same, are the JS engine called the object's constructor to create a new object. The constructor itself is also a normal JS function
Let's take a look at an example
To create a constructor functionfunctionPerson (Name) {THIS.name = name}Each constructor JS engine automatically adds a prototype attribute, which we call a prototype, which is an objectEach object created by the constructor will share the properties and methods above the prototypeconsole.log (typeof Person.prototype) //' object ' // We add Sayname method for Person.prototype Person.prototype.sayName = function (console.log (//Create instance var person1 = New Person ( ' Messi ') var person2 = New Person ( ' Suarez ') person1.sayname () //' Messi ' Person2.sayname () //' Suarez ' person1.sayname = = = Person2.sayname //true
We use the above example to understand the relationship between the constructor-prototype-instance, the three, there are basically several basic concepts
The constructor defaults protoype
to a property that points to its prototype
The constructor's prototype will have a consctructor
property that points to the constructor itself, i.e.
Person.prototype.constructor === Person
Each new
out instance has an implicit __proto__
property that points to the prototype of their constructor, which is
person1.__proto__ === Person.prototypeperson1.__proto__.constructor === Person
With these basic concepts in perspective, let's look at some of the network of JavaScript native constructors, as shown in the following diagram
Quoted StackOverflow
As we understand above, oject itself is a constructor, it is also an object, then
Object.__proto__ === Function.prototype
To make it easy for us to remember, there are a few special concepts that we need to know:
Function
Prototype property to the Function
same object as the prototype.
Function.__proto__ == Function.prototype
Object.prototype.__proto__ === null
typeof Function.prototype === ‘function‘
On the prototype and prototype chain of JavaScript