background

Brendan Eich, the author of JavaScript, designed the programming language simply as a tool for browsers to interact with web pages. He felt that the language needed to be able to do simple things, such as determine whether a user had filled out a form.

Based on the simplicity of the language’s design, Brendan Eich felt that JavaScript did not need to have the “inheritance” mechanism that object-oriented languages like Java have. But given that everything in JavaScript is an object (all data types can be represented as objects), there must be a mechanism to associate all objects together and implement a similar “inheritance” mechanism.

Unlike most object-oriented languages, ES6 did not introduce the concept of classes. JavaScript uses constructors instead of classes to create instances and uses the prototype model to achieve “inheritance”.

The constructor

In JavaScript, constructors are usually used to implement instances. JavaScript has no concept of classes, but it does have special constructors. A constructor is essentially a normal function that acts as a class, creating an instance and initializing it by assigning initial values to its member variables.

Constructors differ from ordinary functions in that constructors should follow the following specifications:

  1. In naming, the constructor must begin with a capital letter;
  2. The method of calling is different. Ordinary functions are called directly, while constructors need to use the new keyword to call.
  3. Inside the constructor, this refers to the newly created instance;
  4. If you want to use the displayed return value, the displayed return value must be an object. Otherwise, the instance is returned.

The prototype

Constructors are used to create instances, so what does that have to do with stereotypes?

What is a prototype

To understand this, look at the following code:

// Step 1: Create a constructor
function Person(name) {
    this.name = name;
    this.sayName = function() {
        console.log(this.name); }}// Step 2: Create an instance
var person = new Person('harry');
Copy the code

In this case, as shown in the figure below, when the constructor is created, a new object is created in the memory space. The property prototype in the constructor refers to the storage space of the object. This object is called the prototype object of the constructor.

For step 2, as shown in the figure below, Person is an instance created by the Person constructor, and inside person will contain a pointer (internal property) to the constructor’s prototype object, called [[prototype]].

Currently, most browsers support the __proto__ property to access the constructor’s prototype object, as in this case, person.__proto__ refers to the object store of Person.prototype.

As we know from the above example, the instance person needs to use the __proto__ attribute if it accesses the prototype object.

In fact, __proto__ is an accessor property (consisting of a getter and a setter), but is not recommended as a property to access [[prototype]], as specified in the JavaScript specification. This property is only available in a browser environment.

[[prototype]] is internal and hidden. When you need to access the internal [[prototype]], you can use the following modern methods:

// Return object obj [[prototype]].
Object.getPrototypeOf(obj);

// Set object obj's [[prototype]] to proto.
Object.setPrototypeOf(obj, proto) 

// Create an empty object with the given proto as [[prototype]] and (optional) property descriptor.
Object.create(proto[, descriptors])
Copy the code

Attribute analysis of archetypes

By default, all prototype objects automatically get a constructor property that contains a pointer to the function in which the prototype resides, i.e. the constructor property points to the constructor itself.

Additionally, person. prototype points to an Object and also contains an internal [[prototype]] pointer to object. prototype, which is an Object. This relationship indicates that Person.prototype is created with Object as the constructor.

It is important to note that prototypes can be rewritten. However, JavaScript specifies that it can only be rewritten as an object. If it is rewritten as any other value (null is not allowed), it is automatically ignored and replaced by a lower level in the prototype chain, which will be discussed below.

The role of archetypes

The role of prototypes is as follows:

  1. Property commonality: stereotypes can store default properties and methods that can be shared across different instances.
  2. Inheritance: borrowing the superclass constructor from the subclass constructor, and then inheriting the prototype properties and methods of the superclass through the prototype, simulating the effect of inheritance;
  3. Save storage space: Combined with point 1, more common properties and methods require less storage space.

Here is the validation code written in conjunction with the prototype:

// The first step is to create a new constructor
function Person(name) {
    this.name = name;
    this.age = 18;
    this.sayName = function() {
        console.log(this.name); }}// The second step is to create instance 1
var person1 = new Person('1');

// The third step is to create instance 2
var person2 = new Person('2');

// Both results are true
person1.__proto__ === Person.prototype;
person2.__proto__ === Person.prototype; 

// No. 1 and No. 2
console.log(person1.name, person2.name);

/ / 18 18
console.log(person1.age, person2.age);
Copy the code

Prototype chain

With the archetypes in mind, let’s move on to the core of inheritance – the archetype chain.

What is a prototype chain

In JavaScript, everything is an object (all data types can be represented by an object). There is a relationship between objects, not an isolated existence, and the relationship between objects is inherited. In JavaScript, the instance object refers to the prototype space of the parent object through the internal property [[prototype]]. The Object’s internal property [[prototype]] is null until it points to the browser’s internal Object Object, which forms a chain to which the prototype points. This chain is called the prototype chain.

Attribute lookup in the stereotype chain

If [[prototype]] is not found, it will continue to search for the prototype of the browser built-in object. If it is not found, it will return undefined. If it is not found, it will return undefined.

Note that there is a difference between accessor properties and data properties in the prototype chain for reading and writing (click on Accessor properties and Data Properties). If an accessor property (let’s say age) is set at some level in the prototype chain, when age is read, the value set by the accessor property is returned. The accessor property is also the highest priority when written. In the reading and writing of data attributes, the data will be searched according to the prototype chain attribute lookup; When writing, write directly to the current object, if the prototype chain has the same property, will be overwritten.

The anatomy of the prototype chain

We can analyze the prototype chain with the following code:

// The first step is to create a new constructor
function Person(name) {
    this.name = name;
    this.age = 18;
    this.sayName = function() {
        console.log(this.name); }}// The second step is to create an instance
var person = new Person('person');
Copy the code

From the above code, we can get the following diagram:

In the first step, the Person constructor is created, and the prototype space is created. In the second step, the new constructor generates the instance Person, whose [[prototype]] points to the prototype space.

__proto__ refers to the built-in Object, because person. prototype is an Object and is created by default by the Object function. Object.prototype is a built-in Object.

Person.__proto__ refers to the built-in anonymous Function, because Person is a Function object. Function.

One more thing to note here is that function.prototype and function.__proto__ both point to the built-in anonymous Function, so that the end of the prototype chain is null without worrying about getting stuck in an infinite loop.

The last

The application of prototype and prototype chain is the essence of JavaScript, which is widely used in many frameworks and libraries. Learning this knowledge well is the first task of front-end ER, and it is also a necessary step for front-end career development.

Come on, workers!