Generous without corner, late, big sound, elephant invisible. — Tao Te Ching

JavaScript Prototype Series (I) Constructors, prototypes, and prototype chains

What is Prototype Inheritance

Function, Object, Null, etc

Introduction to the

Understand what the properties constructor, prototype, [[prototype]], and __proto__ do, as well as conceptual prototypes, prototype chains, and constructors.

Combine the above attributes with the code first and record clear.

The constructor

Constrcutor is a special method for creating and initializing objects created by a class. A constructor is a function in itself, no different from a normal function, but it is usually capitalized for the sake of specification. The difference between a constructor and a normal function is that a function that generates an instance using new is a constructor and calls a normal function directly. Sample code:

    function ConstructorFun (name) {
        this.name = name;
    }
    // Create an instance with the new keyword
    let constructorfun = new ConstructorFun();
Copy the code

ConstructorFun is just a normal function, but when an instance is created using the new keyword, it can be called a constructor;

constructor

With the exception of null and undefined, normal functions have the constructor attribute, whether they are instances generated by new or variables generated by literals.

The code is as follows:

    function ConstructorFun (name) {
        this.name = name;
    }
    // Create an instance with the new keyword
    var constructorfun = new ConstructorFun();
    constructorfun.constructor === ConstructorFun; // true
    var number = 111;
    console.log(number.constructor); ƒ Number() {[native code]}
Copy the code

Constructor extension

  • let a = {}Is actuallylet a = new Object()The syntactic sugar
  • let a = []Is actuallylet a = new Array()The syntactic sugar
  • function Foo(){… Var Foo = new Function(…)
  • You can useinstanceofDetermines whether a function is a constructor of a variable

Manually implement an instanceof function as follows:

    // Emulate the instanceof implementation
    function selfInstanceof (left, right) {  //left represents the left expression and right represents the right expression
        let cur = left.__proto__; // Take the implicit prototype of cur
        let parent = right.prototype; // Take the explicit prototype of right
        while(true) {
            if (cur === null) { // Return false if cur is null
                return false;
            }
            if (cur === parent) { // Return true if cur is the same as parent
                return true;
            }
            cur = cur.__proto__; // If neither of the above conditions is met, continue to search up the prototype chain}}Copy the code

Whether the constructor value can be changed

For reference typesconstructorProperty values can be modified, but are read-only for primitive types.

Note: null and undefined have no constructor attribute.

The prototype

Official explanation of stereotypes: “JavaScript is often described as a prototype-based language ———— Each object has a prototypeobject, from which it inherits methods and properties.” Each function has a special property called prototype. Look at the following code:

    function Foo () {}
    console.log(Foo.prototype);
Copy the code

The effect is shown below:

Foo.prototype
constructor
__proto__
Object.prototype

Constructor Foo has a pointer to the prototype, the prototype Foo. The prototype has a pointer to a constructor Foo prototype. The constructor, use the chart below to show more clearly:

More importantly, any Prototype object has a constructor property that points to this constructor.

proto

Seeing the __proto__ attribute above, each instance object has an implicit prototype attribute (called __proto__) that points to the prototype of the constructor that created the object.

    function Foo (name) { this.name = name; }
    var foo = new Foo();
Copy the code

The renderings are as follows:

new Foo()
foo
__proto__
Foo.prototype

    foo.__proto__ === Foo.prototype; // true
Copy the code

Foo, Foo prototype, Foo. The prototype. The constructor, Foo __proto__ three relations as shown in the figure below:

__proto__
Object.getPrototypeOf()

Changing and inheriting properties by changing an object’s [[Prototype]] property can have a serious impact on performance, and the performance time is not simply spent on obj.__proto__ =… It also affects all objects inherited from the [[Prototype]] statement. If you care about performance, you shouldn’t change an object’s [[Prototype]].

If you want to read or modify an object’s [[Prototype]] property, the following scheme is recommended, but setting the object’s [[Prototype]] is still a slow operation and should be avoided if performance is an issue.

    / / to get
    Object.getPrototypeOf()
    Reflect.getPrototypeOf()

    / / modify
    Object.setPrototypeOf()
    Reflect.setPrototypeOf()
Copy the code

If you want to create a new Object and inherit [[Prototype]] from another Object, object.create () is recommended.

    function Parent() {
        age: 50
    };
    var p = new Parent();
    var child = Object.create(p);
Copy the code

[[Prototype]]

[[Prototype]] is an internal property of an object that external code cannot access directly.

Following the ECMAScript standard, the someObject.[[Prototype]] symbol is used to point to the Prototype of someObject

Prototype chain

Each object has a prototype object, which points to the previous prototype via a __proto__ pointer, inheriting methods and properties from it, while the prototype object may also have a prototype, layer by layer, and so on, eventually pointing to NULL. This relationship is called the Prototype chain, through which one object has properties and methods defined in other objects. It might be more intuitive to look at a classic picture:

Take a look at the following code:

    function Foo () {}
    var foo = new Foo();
    foo.__proto__ === Foo.prototype; // true
    foo.__proto__.__proto__ === Object.prototype; // true
    foo.__proto__.__proto__.__proto__ === null; // true
Copy the code

The prototype and __proto__ pointing problems above are best illustrated in the figure below.

Special Symbol

Symbol is the base data type. It can generate instances from Symbol(123), not from new Symbol(). Symbol is not a constructor, but it has a constructor attribute.

    let sSymbol = Symbol('symbol');
    let errSymbol = new Symbol('symbol'); // Uncaught TypeError: Symbol is not a constructor

    Symbol.constructor; ƒ Symbol()
Copy the code

conclusion

  • Each function object has oneprototypeProperty that points to the prototype of the function object. There is one on the prototype objectconstructorAttribute points toThe constructorItself.
  • Reference typesconstructorProperty value yesModify theIs, but for primitive typesread-only, of course,nullundefinedThere is noconstructorProperties.
  • __proto__Properties inES6Is standardized, but is not recommended due to performance issuesObject.getPrototypeOf().
  • __proto__Is a property that exists on every instance,prototypeProperty of the constructor, doesn’t exist on the instance, so these two are not the same, butfoo.__proto__Foo.prototypePoint to the same object.
  • Each object has a prototype object that passes__proto__A pointer points to the last stereotype, inherits methods and properties from it, and the stereotype object may have a stereotype, layer by layer, and eventually pointsnullThis is the prototype chain.

reference

Rediscover constructors, stereotypes, and stereotype chains

JS Series 2: Prototypes and prototype chains

The object prototype