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

  1. 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

  1. __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

  1. Waste of memory
  2. 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