Let's talk in depth about the principle and implementation of new in JS

Let's talk in depth about the principle and implementation of new in JS

definition

The new operator creates an instance of a user-defined object type or an instance of a built-in object with a constructor.

Use the new [constructor] method to create an object instance, but differences in constructors will result in different instances being created.

Constructor bodies are different

A constructor is also a function. The only difference is the calling method. Any function called with the new operator is a constructor, and a function not called with the new operator is an ordinary function.

Therefore, the constructor can also have a return value, but this will result in different results for new.

No return value

function Person(name) {
  this.name = name;
}

let obj = new Person("Jalenl");
console.log(obj);

Obviously, what is printed is {name:'Jalenl'}

Return Object

function Person(age) {
  this.age = age;
  return { name: "Jalenl" };
}

let obj = new Person(18);
console.log(obj);

What is printed is {name:'Jalenl'}, which means that all the definitions before return are overwritten. What is returned here is an object, what if it is a basic type?

Returns non-object

function Person(age) {
  this.age = age;
  return 1;
}

let obj = new Person(18);
console.log(obj);

Returns {age:21}, which means that return is invalid, and the result is the same as if there is no return. What if there is no this bound internal attribute and the basic data type is returned?

No property binding + returns non-object

function Person(){
    return 1
}
new Person()

The returned value is an empty object {}, as expected.

In summary, the initial result can only be changed when the constructor return returns an object type.

Constructor types are different

The constructor is a normal function

The ECMA-262 3rd. Edition Specification describes the process of creating an object instance:

13.2.2 [[Construct]]
When the [[Construct]] property for a Function object F is called, the following steps are taken:

  1. Create a new native ECMAScript object.
  2. Set the [[Class]] property of Result(1) to "Object".
  3. Get the value of the prototype property of F.
  4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
  5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
  6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
  7. If Type(Result(6)) is Object then return Result(6).
  8. Return Result(1).

To sum up:

  1. Create a new object in memory.
  2. The [[Prototype]] property inside this new object is assigned to the prototype property of the constructor function.
  3. This inside the constructor is assigned to the new object (that is, this points to the new object).
  4. Execute the code inside the constructor (adding properties to the new object).
  5. If the constructor returns an object, then that object is returned; otherwise, the newly created object (empty object) is returned.

The fifth step has already explained why different constructors lead to different new results.

The following is an explanation from MDN:

When the code new Foo(…) is executed, the following things happen:

  1. A new object is created that inherits from Foo.prototype.
  2. Invokes the constructor Foo with the specified arguments and binds this to the newly created object. new Foo is equivalent to new Foo(), that is, no argument list is specified and Foo is called with no arguments.
  3. The object returned by the constructor is the result of the new expression. If the constructor does not explicitly return an object, the object created in step 1 is used. (Generally, constructors do not return values, but users can choose to actively return objects to override the normal object creation steps)

Constructor is an arrow function

When a normal function is created, the engine will create a prototype property (pointing to the prototype object) for this function according to specific rules. By default, all prototype objects automatically gain a property called constructor that points back to the constructor associated with them.

function Person(){
    this.age = 18;
}
Person.prototype
/**
{
    constructor: ƒ Foo()
    __proto__: Object
}
**/

When creating an arrow function, the engine will not create a prototype property for it. The arrow function has no constructor for new to call, so using new to call the arrow function will result in an error!

const Person = ()=>{}
new Person() // TypeError: Foo is not a constructor

Handwritten new

In summary, after being familiar with the working principle of new, we can implement a low-profile version of new by ourselves. The key to implementation is:

  1. Allow instances to access private properties;
  2. Allow instances to access properties on the prototype chain where the constructor prototype (constructor.prototype) is located;
  3. The final result returned by the constructor is a reference data type.
function _new(constructor, ...args) {
    // Constructor type legal judgment if(typeof constructor !== 'function') {
      throw new Error('constructor must be a function');
    }
    //Create a new empty object instance let obj = new Object();
    // Bind the prototype of the constructor to the newly created object instance obj.__proto__ = Object.create(constructor.prototype);
    // Call the constructor and determine the return value let res = constructor.apply(obj, args);
    let isObject = typeof res === 'object' && res !== null;
    let isFunction = typeof res === 'function';
    // If there is a return value and it is an object type, then use it as the return value, otherwise return the previously created object return isObject || isFunction ? res : obj;
};

This low-profile new implementation can be used to create instances of custom classes, but it does not support built-in objects. After all, new is an operator and the underlying implementation is more complicated.

Summarize

This is the end of this article about the principle and implementation of new in JS. For more relevant content about the principle and implementation of new in JS, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed description of the function of new in JS
  • Detailed explanation of the principle and example of the new operator in JavaScript
  • Research on two ways to implement new in JavaScript
  • How to implement JavaScript's new operator yourself
  • Detailed explanation of the role of the new operator in Js
  • Summary of common methods of c# Newtonsoft.Json
  • C# Newtonsoft.Json parses multiple nested json for deserialization example
  • c# add Newtonsoft.Json package operation
  • The new command in JavaScript
  • Handwriting implementation of new in JS

<<:  CSS simulates float to achieve the effect of center text surrounding the image on the left and right

>>:  Design of pop-up windows and floating layers in web design

Recommend

HTML table tag tutorial (27): cell background image attribute BACKGROUND

We can set a background image for the cell, and w...

MySQL string splitting example (string extraction without separator)

String extraction without delimiters Question Req...

Example of how to use CSS3 to layout elements around a center point

This article introduces an example of how CSS3 ca...

Mycli is a must-have tool for MySQL command line enthusiasts

mycli MyCLI is a command line interface for MySQL...

MySQL 5.7.24 installation and configuration method graphic tutorial

MySQL is the most popular relational database man...

How to use tcpdump to capture packets in Linux system

Let me look at the example code first: 1. Common ...

A complete list of commonly used Linux commands (recommended collection)

Table of contents 1. System Information 2. Shutdo...

Detailed tutorial on using VMware WorkStation with Docker for Windows

Table of contents 1. Introduction 2. Install Dock...

How to view the status of remote server files in Linux

As shown below: The test command determines wheth...

18 Web Usability Principles You Need to Know

You can have the best visual design skills in the...

How to use Vue to develop public account web pages

Table of contents Project Background start Create...

Linux tac command implementation example

1. Command Introduction The tac (reverse order of...

jQuery implements nested tab function

This article example shares the specific code of ...