As we all know, Javascript is an object-oriented language, if the object oriented to ask, I will think of two questions, in JS, class and instance object is how to create, class and instance object is how to achieve inheritance.

object-oriented

How do I declare a class

In ES5, there is no concept of classes; instead, they are declared by functions. On ES6, you have the class keyword, which is declared by class

Var Animal = var Animal =function () {
this.name = 'Animal'; }; // es6 class class Animal2 {constructor () {
this.name = 'Animal2';
}
Copy the code

How to create objects

1. Literal Object 2. Display constructor 3.Object.create

Var o1 = {name:'o1'};
var o2 = new Object({name: 'o2'}); // The second way: var M =function (name) { this.name = name; };
var o3 = new M('o3'); Create var p = {name:'p'};
var o4 = Object.create(p);

Copy the code

Class to inherit

How is inheritance implemented? The essence of inheritance is a chain of archetypes

Use constructors to implement inheritance

/** * inherits */ with the constructorfunction Parent1 () {
this.name = 'parent1';
}
Parent1.prototype.say = function() {};function Child1() { Parent1.call(this); Parent1.apply(this,arguments) this.type ='child1';
}
console.log(new Child1(), new Child1().say());
Copy the code

Parent1.call(this); parent1. call(this); The parent constructor is executed in the subclass constructor, changing this via call/apply, so that all properties of the parent constructor are mounted to the subclass instance. Problem: Only the instance properties declared in the superclass constructor are inherited, not the properties and methods of the superclass prototype

Inheritance is implemented with a prototype chain

/** * implements inheritance */ with a prototype chainfunction Parent2 () {
this.name = 'parent2';
this.play = [1, 2, 3];
}
function Child2 () {
this.type = 'child2';
}
Child2.prototype = new Parent2();

var s1 = new Child2();
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);
Copy the code

Child2.prototype = new Parent2(); New Child2().proto === child2. prototype === new Parent2() Inheritance is achieved by following the prototype chain to find new Parent2(). Problem: The stereotype objects in the stereotype chain are shared. Subclasses cannot create private properties from their parent class. For example, when you create two new subclasses s1 and S2, change the properties of S1 and change the properties of S2

Combinatorial inheritance

/** ** combination */function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3() { Parent3.call(this); // The parent constructor executes this.type ='child3'; } Child3.prototype = new Parent3(); Var s3 = new Child3(); var s4 = new Child3(); s3.play.push(4); console.log(s3.play, s4.play);Copy the code

The combinatorial inheritance, which is the prototype-chain + constructor inheritance, solves the problems of the first two methods, but has its drawbacks: when the subclass is instantiated, the superclass constructor executes twice, so there is the following optimization of combinatorial inheritance 1

Optimization of combinatorial inheritance 1

/** * combinatorial inheritance optimization 1 * @type {String}
*/
function Parent4 () {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4 () {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s5 = new Child4();
var s6 = new Child4();
console.log(s5, s6);

console.log(s5 instanceof Child4, s5 instanceof Parent4);
console.log(s5.constructor);
Copy the code

Prototype = new Parent4(); Prototype = Parent4. Prototype; So although the parent class constructor performed only once, but a new problem: unable to determine the s5 is Child4 instance or Parent4 instance Because Child4. Prototype. The constructor to Parent4 instance; If directly add Child4) prototype) constructor = Child4 also not line, so Parent4. Prototype. The constructor also point to Child4, will not be able to distinguish between the parent class instance.

A) constructor === = a) instanceof Instanceof determines whether the __proto__ of the instance object is the same reference as the constructor’s prototype. If A inherits B, B inherits C objects on the prototype chain using instanceof return true

Optimization of combinatorial Inheritance 2(recommended)

/** * combinatorial inheritance optimization 2 */function Parent5 () {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5 () {
Parent5.call(this);
this.type = 'child5'; } // Notice that the object.creat (obj) method is used here, which makes a shallow copy of the obj Object passed in. Prototype = object.create (parent5.prototype); / / modify the constructor to Child5. Prototype. Constructor = Child5Copy the code

Constructor attributes inherit and establish links between subclass and superclass stereotypes

ES6 implements inheritance

The class, extends, and super keywords were introduced to call the super() method in the subclass constructor to call the superclass constructor. In the constructor of a subclass, the this keyword can only be used after super is called, otherwise an error will be reported. This is because subclass instances are built based on processing superclass instances, and only super methods can return superclass instances.

class Child6 extends Parent6 { constructor(x, y, color) { super(x, y); // Call the parent class constructor(x, y) this.color = color; }toString() {
return this.color + ' '+ super.toString(); // super represents the superclass prototype and calls toString()}}Copy the code

Class implementation Principle

Class plays the role of the ES5 constructor in inheritance implementation: the Prototype property, the __proto__ property, and the direction of this property in ES6 has some active modifications. There are two inheritance chains: one implements attribute inheritance and one implements method inheritance.

class A extends B {} A.__proto__ === B; // The inherited attribute a.prototype.__proto__ === b.prototype; // Inheritance methodCopy the code

The __proto__ of a subclass of ES6 is the parent class, and the __proto__ of a subclass’s prototype is the parent class prototype. In ES5, A.__proto__ refers to Function. Prototype, because every constructor is actually built from Function. In ES6, __proto__ refers to the parent class.

Only functions have the Prototype attribute and only objects have the __proto__ attribute; But functions also have a __proto__ attribute, because a Function is also an object, and its __proto__ is equal to function.prototype.

Realization principle of extends

Prototype = object.create (person.prototype); Object. SetPrototypeOf (Man, Person); // Bind this person.call (this);Copy the code

The first two sentences implement inheritance on the stereotype chain, and the last sentence implements inheritance on the constructor.

My blog

Welcome to exchange!