Detailed explanation of the new object process in JavaScript

To create a new instance of Person, the new operator must be used. Calling the constructor in this way will actually go through the following 4 steps:

  1. Create a new object;
  2. Assign the scope of the constructor to the new object (so this points to this new object);
  3. Execute the code in the constructor (add attributes to this new object);
  4. Return a new object;

1. The new operator

After the introduction of the above basic concepts and the addition of the new operator, we can complete the traditional object-oriented class + new method to create objects. In JavaScript, we call this type of method Pseudoclassical.

Based on the above example, we execute the following code

var obj = new Base();

What is the result of this code? The object model we see in the Javascript engine is:
Insert picture description here
What does the new operator do? It is actually very simple, and it does three things.

var obj  = {
    
    };
obj.proto = Base.prototype;
Base.call(obj);

第一行,我们创建了一个空对象obj;
第二行,我们将这个空对象的 __proto__ 成员指向了 Base 函数对象 prototype 成员对象;
第三行,我们将 Base 函数对象的 this 指针替换成obj,然后再调用 Base 函数,于是我们就给 obj 对象赋值了一个 id 成员变量,
这个成员变量的值是 ”base” ,关于 call 函数的用法。

What effect will we have if we add some functions to the Base.prototype object?

Base.prototype.toString = function() {
    
    
   return this.id;
}

Then when we use new to create a new object, according to the characteristics of proto , the toString method can also be accessed as a new object method.
So we saw: in the
construction of the sub-object, we set the member variables of the'class' (for example: id in the example), and in the construction of the prototype of the sub-object, we set the public method of the'class'. So through the function object and Javascript's unique __ proto __ and prototype members and the new operator, the effect of class and class instantiation is simulated.

2. What happened during the new operation

For most front-end developers, it is a very common operation to obtain a corresponding instance of a new constructor or class.
In the following example, a simple process of creating an instance is realized through the constructor and the class class respectively.

// ES5构造函数
let Dog = function (name, age) {
    
    
  this.name = name;
  this.age = age;
};
Dog.prototype.sayName = function () {
    
    
  console.log(this.name);
};
const myDog = new Dog('汪汪', 2);
myDog.sayName() // '汪汪'

// ES6 class类
class Cat {
    
    
  constructor(name, age) {
    
    
    this.name = name;
    this.age = age;
  }
  sayName() {
    
    
    console.log(this.name);
  }
};
const myCat = new Cat('QIU', 3);
myCat.sayName(); // QIU

But new should not be like a black box. In addition to knowing the result, we should also understand the process.

In a more intuitive sense, when we new a constructor, the instance obtained inherits the constructor's construction properties (this.name these) and the properties on the prototype .
In the book "JavaScript Patterns", the process of new is more straightforward. When we new a constructor, there are three main steps:

  1. Create an empty object, assign its reference to this, and inherit the prototype of the function;
  2. Add properties and methods to this object through this;
  3. Finally return the new object pointed to by this, which is the instance (if no other objects are returned manually);

Rewrite the above example, it is probably like this:

// ES5构造函数
let Dog = function (name, age) {
    
    
  // 1.创建一个新对象,赋予this,这一步是隐性的,
  //   let this = {};
  // 2.给this指向的对象赋予构造属性
  this.name = name;
  this.age = age;
  // 3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
  // return this;
};
const myDog = new Dog();

This should not be difficult to understand, you should have seen operations similar to the following code in your work, assign this to a new variable (such as that), and finally return this variable

// ES5构造函数
let Dog = function (name, age) {
    
    
  let that = this;
  that.name = name;
  that.age = age;
  return that;
};
const myDog = new Dog('汪汪', 2);

Why do you write this?
I said earlier that the creation and return of this is implicit, but in order to make the construction process more visible and easier to maintain in the work, the above method of using that instead of this and manually returning that is
also verified. The two steps of sex do exist.

But the above explanation is not perfect for me. It only describes how the properties of the constructor are inserted into the instance, and it does not say how the properties on the prototype are inherited by the instance.

In the re-learning front-end column of the Winter Great God, I saw a description that was more in line with my mind and also in line with the principle:

  • Use the prototype property of the constructor as the prototype to create a new object;
  • Pass this (that is, the new object in the previous sentence) and the call parameters to the constructor and execute;
  • If the constructor does not manually return the object, it returns the object created in the first step;

No matter what you say here, you should probably know the new process: an object will be created, this object will inherit the prototype of the constructor and the properties on the prototype, and finally it will be returned to such a process as an instance. Knowing the principle, let's manually implement a simple new method.

3. Implement a simple new method

// 构造器函数
let Dog = function (name, age) {
    
    
  this.name = name;
  this.age = age;
};
Dog.prototype.sayName = function () {
    
    
  console.log(this.name);
};

// 定义的new方法
let newMethod = function (Dog, ...rest) {
    
    
  // 1. 以构造器的 prototype 属性为原型,创建新对象;
  let myDog = Object.create(Dog.prototype);
  // 2. 将this和调用参数传给构造器执行
  Dog.apply(myDog, rest);
  // 3. 返回第一步的对象
  return myDog;
};

// 创建实例,将构造函数 Dog 与形参作为参数传入
const myDog = newMethod(Dog, '汪汪', 2);
myDog.sayName() // '汪汪';

// 最后检验,与使用new的效果相同
console.log( myDog instanceof Dog ) // true
console.log( myDog.hasOwnProperty('name') ); // true
console.log( myDog.hasOwnProperty('age') ); // true
console.log( myDog.hasOwnProperty('sayName') );// false

Guess you like

Origin blog.csdn.net/ZYS10000/article/details/113447144