This document has been updated on Github.

The use of the new

// Define the constructor
function Person (name) {
  this.name = name;
}

Person.prototype.age = 26;

// Create an instance
var person = new Person('Tangerine on the front');

// Call the instance
console.log(person.name); // Front tangerine
console.log(person.age); / / 26
console.log(person); // Person {name: "前端橘子君"}
Copy the code

This is a very common instance that calls properties on the instance and on the stereotype, respectively.

The principle of

According to the constructor pattern in Chapter 6 of JavaScript Advanced Programming, creating an instance with the new operator goes through four phases:

  • Create a new object
  • 2. Assign the scope of the constructor to the new object (thus this refers to the new object)
  • 3. Execute the code in the constructor (add properties to the new object)
  • 4, return the new object

Now that we know the steps, we can do it.

implementation

The second step may be more difficult to understand. You need to know about prototypes and prototype chains. For details, see prototypes and prototype chains.

Let’s ignore step 2 and implement an initial version.

/** * Implements the new operator *@param The ctor constructor *@param The args constructor takes an argument */
function _new (ctor, ... args) {
  // First, create a new object
  var obj = {};
  // Step 2: ignore
  
  // The third step is to execute the constructor and mount its initial properties on the new objectctor.call(obj, ... args);// Return the new object
  return obj;
}

// Define the constructor
function Person (name) {
  this.name = name;
}
// Add attributes to the constructor stereotype
Person.prototype.age = 26;

/ / call
var person = _new(Person, 'Tangerine on the front')
console.log(person.name); // Front tangerine
console.log(person.age); / / 26
Copy the code

As you can see, we can call the name property of the instance, but we can’t call the age, why property on the Person stereotype.

Because Person is not on the prototype chain of Person, in other words, Person is not an instance of Person. Verify that.

console.log(person instanceof Person); // false
Copy the code

Not surprisingly, let’s first look at the person and the person prototype chain

The prototype chain of Person and Person

For those unfamiliar with prototypes and prototype chains, see Prototypes and Prototype chains, which will teach you what prototypes and prototype chains are in plain English.

Person instance -> object. prototype -> null

Person -> object. prototype -> null

The expected prototype chain: Person instance -> constructor person -> object. prototype -> NULL

The complete code

Now that we know what prototype chain we want, we can observe that simply referring the prototype chain of the Person instance (__proto__) to the prototype of the constructor Person.

obj.__proto__ = ctor.prototype

Isn’t that what you need to do in step two? Put it in and try again.

/** * Implements the new operator *@param The ctor constructor *@param The args constructor takes an argument */
function _new (ctor, ... args) {
  // First, create a new object
  var obj = {};
  // Step 2: ignore
  obj.__proto__ = ctor.prototype
  // The third step is to execute the constructor and mount its initial properties on the new objectctor.call(obj, ... args);// Return the new object
  return obj;
}

// Define the constructor
function Person (name) {
  this.name = name;
}
// Add attributes to the constructor stereotype
Person.prototype.age = 26;

/ / call
var person = _new(Person, 'Tangerine on the front')
console.log(person.name); // Front tangerine
console.log(person.age); / / 26
console.log(person instanceof Person); // true
Copy the code

Another consideration here is that when the constructor returns a reference type, such as object, array, function, or new, the operator should return the result of the constructor.

Ctor.call (obj,… Args) returns whether the type is a reference type, if so, returns the result of cTOR execution, otherwise returns obj.

function _new (ctor, ... args) {
  // First, create a new object
  var obj = {};
  // Step 2: ignore
  obj.__proto__ = ctor.prototype
  // The third step is to execute the constructor and mount its initial properties on the new object
  varresult = ctor.call(obj, ... args);// Return the new object
  return typeof result === 'object' ? result : obj;
}
Copy the code

Thank you, Polo. Blowing snow, dougwen fat Tiger’s correction.


For more documentation, see:

Online address [front Tangerine gentleman]

GitHub Warehouse [Front Tangerine]