The constructor Person is created in javaScript’s object-creation method-constructor mode.

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age); }}var person1 = new Person('Tom'.18);
var person2 = new Person('Harry'.28);
Copy the code

To create an instance of a constructor, use the new operator. Calling the constructor in this way goes through the following steps:

  • Create a new object
  • Assign the constructor’s scope to the new object, and this refers to the newly created object
  • Execute the constructor to add attributes to the new object
  • Return a new object

So how does the new operator work, and what does it do when you use it? Modify the above constructor to return undefined, NaN, a string, and NULL, respectively.

 function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age);
    }
    return;
}
console.log(Person('Tom'.18)); // undefined
console.log(new Person('Harry'.28));   // Person {name: "Harry", age: 28, say: ƒ}
Copy the code
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age);
    }
    return NaN;
}
console.log(Person('Tom'.18)); // NaN
console.log(new Person('Harry'.28));   // Person {name: "Harry", age: 28, say: ƒ}
Copy the code
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age);
    }
    return `My name is The ${this.name}. I'm The ${this.age} years old.`;
}
console.log(Person('Tom'.18)); // My name is Tom. I'm 18 years old.
console.log(new Person('Harry'.28));   // Person {name: "Harry", age: 28, say: ƒ}
Copy the code
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age);
    }
    return null;
}
console.log(Person('Tom'.18)); // null
console.log(new Person('Harry'.28));   // Person {name: "Harry", age: 28, say: ƒ}
Copy the code

When called as a normal function, return the return value of the function (undefined/NaN/ string /null…). . When called as a constructor, the return value (undefined/NaN/ string /null) will be ignored and the newly created object will be returned.

Modify the above constructor to return an object.

 function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function () {
        console.log(this.name + ' ' + this.age);
    }
    return { name, age };
}
console.log(Person('Tom'.18)); // {name: "Tom", age: 18}
console.log(new Person('Harry'.28));   // {name: "Harry", age: 28}
Copy the code

When called as a normal function, the return value of the function is returned, and when called as a constructor, the return value of the function is returned.

To sum up, with reference to the documents:

When we use the new operator, we make some judgments about the return value of the constructor:

  • If the return value is an underlying data type, the return value is ignored;
  • If the return value is a reference data type, the return value using the constructor return, the new operator, is invalid.

Based on the above, simulate the internal processing details of New.

// The NewFn function takes an arbitrary number of arguments,
// The first argument is the constructor (which is the target function of the new operator),
// The remaining arguments are arguments to the constructor.
function NewFn(ConstructFn, ... args) {
    // Create a new object
    let obj = Object.create({}); // let obj = {}
    // Assign the scope of the constructor to the new object.
    Object.setPrototypeOf(obj, ConstructFn.prototype); // obj.__proto__ = ConstructFn.prototype
    // Execute ConstructFn in the scope of obj and pass in the args argument to add attributes to the new object
    let res = ConstructFn.apply(obj, args);
    // Determine the return value of the original constructor and return the final result
    return res instanceof Object ? res : obj;
}
Copy the code