Use constructors to create objects
The easiest way to create an object in Javascript is to use the literal approach
var obj = {}
obj.a = 1
obj.b = 2
Copy the code
But as objects become more complex, the downside of this approach becomes apparent: you have to write a lot of repetitive code every time you create an object. Therefore, we can use the constructor approach
function F (foo, bar) {
this.a = 1
this.b = 2
this.foo = foo
this.bar = bar
}
var ins = new F(11.22)
Copy the code
This approach solves the problem of literals, but it also has drawbacks. You can see that in each instance, property A and property B are the same, so can they be separated from each other? Thus, the concept of a prototype is born.
Templates vs. prototypes
prototype
For all the common properties mentioned above, JS provides a property prototype defined on the constructor that points to an object. Prototype is used as the template each time the instance object is created, so the code above becomes:
function F (foo, bar) {
this.foo = foo
this.bar = bar
}
F.prototype.a = 1
F.prototype.b = 2
var ins = new F(11.22)
Copy the code
F. protoType is called the stereotype of ins, properties on F. protoType are called stereotype properties, and properties in INS are called instance properties
__proto__
So the question is, how exactly are instance properties and prototype properties handled in a computer? The most intuitive idea is to copy func. prototype into each instance, or to think of it as a copy of func. prototype, and then add instance properties to that copy, so that each instance has access to the properties and methods of the prototype, as described earlier in the template. But there are two drawbacks to this approach
- Waste of memory
- Each prototype object is independent of each other, and the change of prototype attributes cannot be dynamically represented in the instance
The first is unquestionable, but for the second, consider creating ins1 and ins2 from the func. prototype template, modifying an attribute on func. Prototype, and then creating ins3. Since there is a separate copy of func.Prototype on each instance, changes on func.Prototype do not manifest on the old instance.
So Javascript takes a second approach to this problem: take the prototype object as a separate object, and access it in the instance through a pointer, that is, __proto__. In this way, memory is saved, and the __proto__ pointer on each instance points to the same prototype object, making the prototype dynamic, that is, changes on the prototype can be reflected in each instance.
Prototype is an attribute of the constructor Func that points to an object, the template of the subclass instance. When new Func(), Func. Prototype is used as the template of the ins instance
__proto__, can be understood as a pointer to an object that points to its prototype, the constructor’s prototype object func. prototype, i.e. ins.__proto__=== func.prototype
Prototype chain
Once you understand the concept of a prototype, the prototype chain is relatively simple. A prototyped chain can be thought of as a linked list, except that the list generally looks back through the next pointer and the prototyped chain looks back to the ancestor through the __proto__ pointer. The prototype of each constructor points to the prototype object (template), and the __proto__ of each instance object points to the constructor’s prototype.
var ins = new Func()
ins.__proto__ === Func.prototype
Copy the code
The next pointer points to null. What about the prototype JS chain? The prototype chain has an end. Object. Prototype. Prototype = new Object(); prototype = new Object(); Func. Prototype. __proto__ = = = Object. The prototype.
var ins = new Func()
ins.__proto__ === Func.prototype
Func.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null // This is the end!!
Copy the code
The prototype chain is quite complex, and there will be more articles on inheritance and the prototype chain of functions