A good understanding of the constructor and how it is executed will help us learn more about prototypes and prototype chains.

1. What is a constructor

In JavaScript, functions called with the new keyword are called constructors. Constructors usually start with a capital letter

Why use constructors?

Study each concept not only to know what it is, but also to know why and what kind of problem it solves.

For example, we want to input the personal information of every student in Class 1, Grade 1, so we can create some objects, such as:

Var p1 = {name: 'zs', age: 6, gender: 'male ', hobby: 'basketball'}; Var p2 = {name: 'ls', age: 6, gender: 'female ', hobby: 'dancing'}; Var p3 = {name: 'ww', age: 6, gender: 'female ', hobby: 'singing'}; Var p4 = {name: 'zl', age: 6, gender: 'male ', hobby: 'football'}; / /...Copy the code

As above, we can treat each student’s information as an object. However, we will find that we write a lot of meaningless code repeatedly. For example, name, age, gender, and hobby. If there are 60 students in this class, we have to repeat it 60 times.

This is where the advantages of constructors come into play. We found that each student had the name, gender, and hobby attributes, but they were all different, so we passed them in as arguments to the constructor. Since we are all first-grade students, age is basically 6 years old, so we can write death, and we can deal with it separately in special cases. At this point, we can create the following function:

function Person(name, gender, hobby) {
    this.name = name;
    this.gender = gender;
    this.hobby = hobby;
    this.age = 6;
} 
Copy the code

Once the above function is created, we can call it with the new keyword, that is, we can create the object with the constructor.

Var p1 = new Person('zs', 'male ', 'basketball'); Var p2 = new Person('ls', 'female ', 'dancing'); Var p3 = new Person('ww', 'female ', 'singing'); Var p4 = new Person('zl', 'male ', 'football'); / /...Copy the code

At this point, you will find it very convenient to create objects. So, although the process of encapsulating the constructor is a bit of a hassle, once it is wrapped, it becomes very easy to create the object again, which is why we use constructors.

When you use object literals to create a series of objects of the same type that may have similar characteristics (attributes) and behaviors (methods), you create a lot of duplicate code, which can be reused using constructors.

The execution of the constructor

Let me start with some basic concepts.

function Animal(color) {
 this.color = color;
} 
Copy the code

When a function is created, we do not know whether it is a constructor or not, even if the function name is uppercase, as in the example above. A function can only be called as a constructor if it is called with the new keyword. Like this:

var dog = new Animal("black"); 
Copy the code

We will discuss only the execution of the constructor, which is called with the new keyword.

Let’s use the Person example above.

function Person(name, gender, hobby) { this.name = name; this.gender = gender; this.hobby = hobby; this.age = 6; } var p1 = new Person('zs', 'man ', 'basketball');Copy the code

In this case, the constructor will execute as follows:

(1) When called with the new keyword, a new memory space is created, marked as Animal instance.

(2) The this inside the function body points to the memory

Through the above two steps, we can come to this conclusion.

Var p2 = new Person('ls', 'female ', 'dancing'); #f2 var p3 = new Person('ww', 'female ', 'singing'); // Create a new memory #f3Copy the code

Each time an instance is created, a new memory space is created (#f2, #f3). When #f2 is created, this in the function body points to #f2, and when #f3 is created, this in the function body points to #f3.

Adding an attribute to this is the same as adding an attribute to the instance.

  1. Return this by default

Since this inside the function body refers to the newly created memory space, this is returned by default, which is the same as #f1 in the figure above. At this point, the memory space of #f1 is accepted by the variable P1. That is, the variable p1, which holds the memory address #f1, is marked as an instance of Person.

This is the entire execution of the constructor.

The return value of the constructor

The last step in constructor execution is to return this by default. By implication, there are other cases for the return value of a constructor. Let’s talk about the return value of the constructor.

(1) Return this by default without manually adding a return value

function Person1() {
 this.name = 'zhangsan';
}

var p1 = new Person1(); 
Copy the code

According to the above, let’s review. First, when called with the new keyword, a new memory space #f11 is generated and marked as an instance of Person1; Next, the this inside the function body points to the memory space #f11; Execute code inside the function body; Since this inside the function body points to this memory space, which is received by the variable P1, p1 will have a name attribute with a value of ‘zhangsan’.

p1: {
 name: 'zhangsan'
} 
Copy the code

(2) Manually add a return value for the primitive data type, and return this

function Person2() {
 this.age = 28;
 return 50;
}

var p2 = new Person2();
console.log(p2.age);   // 28
p2: {
 age: 28
} 
Copy the code

If the above call were a normal function, the return value would be 50.

(3) Manually add the return value of a complex data type (object), and finally return the object

Let’s go straight to the example

function Person3() {
 this.height = '180';
 return ['a', 'b', 'c'];
}

var p3 = new Person3();
console.log(p3.height);  // undefined
console.log(p3.length);  // 3
console.log(p3[0]);      // 'a' 
Copy the code

Let’s do another example

Function Person4() {this.gender = 'male '; Return {gender: 'neutral'}; } var p4 = new Person4(); console.log(p4.gender); // 'neutral'Copy the code

5. Must constructors begin with a capital letter?

It’s all case sensitive

6. Can I run the constructor without the new keyword? If nothing goes wrong, what is the difference between calling the constructor with new and not new?

  1. Call a function using the new operator

Example:

function Person(name){
  this.name = name;
  this.say = function(){
    return "I am " + this.name;
  }
}

var person1 = new Person('nicole');
person1.say(); // "I am nicole" 
Copy the code

When we call the constructor with new, the following changes happen inside the function:

Create a this variable that points to an empty object. And the object inherits the prototype of the function; Properties and methods are added to the object referenced by this; Return this implicitly (if no other object is explicitly returned) using a pseudoprogram to show the above changes:

Function Person(name){// Create this variable to point to the empty object var this = {}; // Attributes and methods are added to the object referenced by this.name = name; this.say = function(){ return "I am " + this.name; } // Return this; }Copy the code

Person1.say () returns the string “I am nicole”. Person1.say () returns the string “I am nicole”.

Tips:

If the return object is specified, the this object may be lost.

function Person(name){ this.name = name; this.say = function(){ return "I am " + this.name; } var that = {}; that.name = "It is that!" ; return that; } var person1 = new Person('nicole'); person1.name; // "It is that!"Copy the code

2. Call the function directly

If the function is called directly, the this object points to the window and does not return any object by default (unless explicitly declared to return a value).

Using the Person function as an example, call the Person function directly:

var person1 = Person('nicole');
person1; // undefined
window.name; // nicole 
Copy the code

As you can see, the result of calling the constructor directly is not what we want.

3. Summary

To prevent the constructor from being called because you forgot to use the new keyword, you can force a call to the new keyword with some criteria, as follows

function Person(name){ if (! (this instanceof Person)) { return new Person(name); } this.name = name; this.say = function(){ return "I am " + this.name; } } var person1 = Person('nicole'); console.log(person1.say()); // I am nicole var person2 = new Person('lisa'); console.log(person2.say()); // I am lisaCopy the code