1. What are the methods of creating objects

Js is not used in general object-oriented languages. ES6 did not have the concept of classes before, but functions can be used to simulate, resulting in reusable object creation

1.1 Factory Mode

Functions are used to encapsulate the details of creating objects, and functions are called to achieve the purpose of reuse.

However, the object created cannot be associated with a type, simply encapsulating reusable code without establishing the relationship between the object and the type

1.2 Constructor pattern

Every function in JS can be a constructor, so long as a function is called by new, it can be called a constructor

Executing the constructor first creates an object, then points the prototype of the object to the constructor’s prototype property, then points this in the execution context to the object, and finally executes the entire function, returning the newly created object if the return value is not an object.

Because the value of this refers to the newly created object, you can use this to assign a value to the object.

The advantage of the constructor pattern over the factory pattern is that the object created is associated with the constructor, so that the type of the object can be identified from the stereotype. However, constructors have the disadvantage of causing unnecessary creation of function objects, because in JS function is also an object, so if the object property contains functions, it will create a new function object every time, wasting unnecessary memory space

1.3 Prototype Mode

Use the prototype object to add common properties and methods using the function’s Prototype property.

However, there are some problems with this pattern. One is that there is no way to initialize a value by passing in a parameter, and the other is that if there is a value of a reference type such as Array, then all instances share the same object, and a change in the reference type value of one instance affects all instances.

1.4 Use constructors and stereotypes together

The constructor initializes the properties of the object, and the prototype object implements the reuse of function methods

1.5 Dynamic prototype mode

By moving the creation of the stereotype method assignment inside the constructor, we can achieve the effect of assigning the stereotype object only once the first time the function is called by checking whether the attribute exists or not. This approach nicely encapsulates the above blending patterns.

1.6 Parasitic constructor pattern

Extends the instantiated object at instantiation time, based on an existing type. This extends the object without modifying the original constructor. It has the same disadvantage as the factory pattern in that it cannot recognize objects.

2. The inheritance

2.1 Inheritance of prototype chain

Use the parent class instance as a subclass prototype

Advantages: method reuse

Disadvantages: Cannot pass parameters when creating subclass instances; Subclass instances share reference properties (such as arr properties) of the parent constructor

The function the Parent (name) {enclosing name = name | | 'father'; This.arr = [1]; this.arr = [1]; this.arr = [1]; // (this attribute, } parent.prototype. say = function() {console.log('hello')} function Child(like) { this.like = like; } Child. Prototype = new Parent() But at the moment the Child. The prototype. The constructor = = Parent Child. The prototype. The constructor = Child / / correction constructor to let boy1 = new Child let () Boy2 = new Child(); boy2 = new Child(); boy2 = new Child(); boy2 = new Child(); // The arr attribute of boy1 was changed, and the arr attribute of boy2 was changed, because the parent constructor's instance attribute arr was added to the child.prototype; If boy1.arr is modified, the properties of boy2.arr will change console.log(boy2.arr); // [1,2] note 1: modify the name attribute of boy1, it will not affect boy2.name. Because setting boy1.name is equivalent to adding a name attribute to the subclass instance. Note 2: console.log(boy1.constructor); // Parent you will notice that the instance constructor is Parent. In fact, we want the constructor of the subclass instance to be Child, so remember to fix the constructor pointer. Repair is as follows: the Child. The prototype. The constructor = Child;Copy the code

2.2 Borrowing constructors

Core: To enhance a subclass instance by borrowing the parent class’s constructor is to copy the instance attributes of the parent class to the subclass.

Advantages: 1. Independent between instances.

2. Create a subclass instance that can pass arguments to the parent class constructor. Subclass instances do not share reference properties of the parent class constructor. Attributes such as arr

3. Multiple inheritance (inheriting multiple parent classes through multiple calls or apply)

Disadvantages: 1. The methods of the parent class cannot be reused; Methods cannot be reused because they are defined in the parent constructor (because the method is created every time an instance of a subclass is created). Say method, for example. (Methods should be reused and shared)

2. A subclass instance cannot inherit properties from its parent class. (Because there are no prototypes)

function Parent(name) { this.name = name; This.arr = [1]; this.arr = [1]; this.arr = [1]; This.say = function() {this.say = function() {this.say = function() { Console. log('hello')}} function Child(name,like) {Parent. Call (this,name); // This. Like = like; } let boy1 = new Child(' apple','apple'); Let boy2 = new Child(' xiaomin ', 'orange '); // Console. log(boy1.name, boy2.name) can be passed to the parent constructor; Boy1.arr. Push (2); boy1.arr. Push (2); console.log(boy1.arr,boy2.arr); // [1,2] [1] // Drawback 1: methods cannot reuse console.log(boy1.say === boy2.say) // false (boy1 and boy2 say methods are independent, not shared) // drawback 2: methods cannot reuse console.log(boy1.say === boy2.say) // Walk = function () {// Define a walk method on the prototype object of the Parent class. Console. log(' I can walk ')} boy1.walk; // undefined (specify instance, cannot get method on superclass prototype)Copy the code

2.3 Combination Inheritance

Core: Inherits the attributes of the parent class and retains the advantages of passing arguments by calling the parent constructor. Then the function reuse is realized by using the parent class instance as the prototype of the subclass.

Advantages: 1. Keep the constructor advantage: create subclass instances, can pass arguments to the parent class constructor.

2. Retaining the advantages of prototype chain: methods of the parent class are defined on the prototype object of the parent class, which can realize method reuse.

3. Reference attributes of the parent class are not shared. For example, the ARR attribute

Disadvantages: Because the constructor of the parent class is called twice, there is an extra copy of the parent instance attribute

Note: ‘combination inherited this way, remember to repair the Child. The prototype. The constructor

function Parent(name) { this.name = name; This.arr = [1]; this.arr = [1]; this.arr = [1]; // (this attribute, Console. log('hello')} function Child(name,like) {console.log('hello')} function Child(name,like) {Parent. Call (this,name,like) // core first this.like = like; } Child. Prototype = new Parent () / / core of the second Child. The prototype. The constructor = Child / / correction constructor to let boy1 = new Child(' apple','apple') let boy2 = new Child(' orange','orange') console.log(boy1.name,boy1.like); Log (boy1.say === boy2.say) // true // Advantage 3: console.log(boy1.say === boy2.say) The referenced properties of the parent class are not shared, such as the arr property boy1.arr.push(2) console.log(boy1.arr,boy2.arr); // [1,2] [1] No arR attribute is shared. // Disadvantage 1: There is an extra parent instance attribute because the parent constructor was called twiceCopy the code

2.4 Original inheritance (optimization of combination inheritance)

Core:

In this way, the instance attributes of the parent class are removed so that when the constructor of the parent class is called, the instance is not initialized twice, avoiding the disadvantages of combinatorial inheritance.

Advantages: 1. Call the superclass constructor only once.

2. Preserve the advantages of constructors: create subclass instances and pass arguments to the superclass constructor.

3. Retaining the advantages of prototype chain: instance methods of the parent class are defined on the prototype object of the parent class, which can realize method reuse.

Disadvantages:

1. After modifying the pointer to the constructor, the parent instance’s constructor pointer also changes (which we don’t want).

Note: ‘combination inherit optimizing 1’ this way, remember to repair the Child. The prototype. The constructor

The reason is that you cannot determine whether the immediate constructor of a subclass instance is a subclass constructor or a superclass constructor.

function Parent(name) { this.name = name; This.arr = [1]; this.arr = [1]; this.arr = [1]; // (this attribute, Console. log('hello')} function Child(name,like) {console.log('hello')} function Child(name,like) {Parent. Call (this,name,like) // core this.like = like; } Child. Prototype = Parent. Prototype - here is repair the constructor to code - > Child. The prototype. The constructor = Child let boy1 = new Child (' red ', 'apple') let boy2 = new Child(' orange','orange') let p1 = new Parent(' orange','orange') Console. log(boy1.say === boy2.say) // true // Disadvantage 1: When the reference to the subclass constructor is fixed, the reference to the constructor of the superclass instance will also change. Before fixing: console.log(boy1.constructor); / / Parent fixing code: Child. The prototype. The constructor = Child after repair, the console. The log (boy1. Constructor); // Child console.log(p1.constructor); // Child = Parent Parent. Prototype () {constructor (); Parent. Prototype () {constructor (); When you change the Construtor attribute of a subclass instance, the orientation of all constructors will change.Copy the code

2.5 Parasitic combination Inheritance — the perfect way

function Parent(name) { this.name = name; This.arr = [1]; this.arr = [1]; this.arr = [1]; // (this attribute, Console. log('hello')} function Child(name,like) {console.log('hello')} function Child(name,like) {Parent. Call (this,name,like) // core this.like = like; } // The core is separated by creating intermediate objects, subclass archetypes, and superclass archetypes. It's not the same, which avoids the disadvantage of method 4. Child. The prototype = Object. The create (Parent. The prototype) / / here is repair constructor code points to the Child. The prototype. The constructor = Child let boy1 = new Child(' apple','apple') let boy2 = new Child(' orange','orange') let p1 = new Parent(' apple') Child. The prototype. The constructor = Child after repair, the console, log (boy1. Constructor); // Child console.log(p1.constructor); / / the Parent is perfectCopy the code