The class and extends keywords are used in es6 to implement inheritance. The class keyword was introduced in ES6 to declare a class, and class (class) can be inherited through the extends keyword, allowing the subclass to inherit the attributes and methods of the parent class. The syntax is "class parent class name {...} class subclass name extends parent class name {...};".
The operating environment of this tutorial: Windows 7 system, ECMAScript version 6, Dell G3 computer.
In es6, the class keyword and the extends keyword can be used to implement inheritance.
1. Introduction
Class can pass extends The keyword implements inheritance, allowing the subclass to inherit the properties and methods of the parent class. This is much clearer and more convenient than ES5's implementation of inheritance by modifying the prototype chain.
//父类 class Point { ... } //子类 class ColorPoint extends Point { constructor(x, y, color) { super(x, y); this.color = color; } toString() { return this.color + '' + super.toString(); // 调用父类的toString方法 } }
In the above code, the super keyword appears inside the constructor method and toString method. Super here represents the constructor of the parent class, which is used to create a new instance object of the parent class.
ES6 stipulates that subclasses must call super() in the constructor method, otherwise an error will be reported. This is because the subclass's own this object must first be shaped through the parent class's constructor to obtain the same object as the parent class. The same instance properties and methods, and then add the subclass's own instance properties and methods.
This is because in the inheritance mechanism of ES5, an instance object of an independent subclass is first created, and then the methods of the parent class are added to this object, that is, "instance first, "Inherit first"; ES6's inheritance mechanism is to first add the attributes and methods of the parent class to an empty object, and then use the object as an instance of the subclass, that is, "inherit first, instance last" .
This means that every time a new subclass instance is created, the constructor of the parent class must be run once
class Foo { constructor() { console.log(1); } } class Bar extends Foo { constructor() { super(); console.log(2); } } const bar = new Bar(); // 1 2
In the above code, when the subclass Bar creates a new instance, it will output 1 and 2, this is when the factor class constructor calls super(), the parent class constructor will be executed once. This keyword can be used only after calling super in the constructor of a subclass, otherwise an error will be reported. This is because the construction of a subclass instance must first complete the inheritance of the parent class. Only the super method can allow the subclass instance to inherit the parent class.
class Point { constructor(x, y) { this.x = x; this.y = y; } } class ColorPoint extends Point { constructor(x, y, color) { this.color = color; super(x, y); this.color = color; } }"
If the subclass does not define a constructor method, this method will be added by default, and super will be called in it. That is to say, any subclass has a constructor method regardless of whether it is explicitly defined.
class Point { constructor(x, y) { this.x = x; this.y = y; } } class ColorPoint extends Point { } let cp = new ColorPoint(25, 8); console.log(cp); //{x: 25, y: 8} class ColorPoint extends Point { constructor(...args) { super(...args); } } let cp = new ColorPoint(25, 8); console.log(cp); //{x: 25, y: 8}
2. Inheritance of private properties and private methods
All properties and methods of the parent class will be inherited by the subclass, except for private properties and methods. Subclasses cannot inherit the private properties of the parent class, or private properties can only be used in the class in which they are defined.
class Foo { #p = 1; #m() { console.log('hello'); } } class Bar extends Foo { constructor() { super(); console.log(this.#p); // 报错 this.#m(); // 报错 } }
In the above example, if the subclass Bar calls the private properties or private methods of the parent class Foo, an error will be reported.
If the parent class defines read and write methods for private properties, the subclass can read and write private properties through these methods.
class Foo { #p = 1; getP() { return this.#p; } } class Bar extends Foo { constructor() { super(); console.log(this.getP()); // 1 } }
3. Inheritance of static properties and methods
The static properties and static methods of the parent class will also be inherited by the subclass.
class A { static hello() { console.log('hello world'); } } class B extends A { } B.hello() // hello world
In the above code, hello()
is a static method of class A
, B
inherits A
, and also inherits A
's static method.
Note that static properties are inherited through shallow copy. If the inherited property is a primitive data type, operating the inherited static properties in the subclass will not affect the parent class, but if the inherited property is an object , then the subclass will be impressed by the parent class when modifying this attribute
class C { static foo = 100; } class D extends C { constructor() { super(); D.foo--; } } const d = new D(); C.foo; // 100 D.foo; // 99 class A { static foo = { n: 100 }; } class B extends A { constructor() { super(); B.foo.n--; } } const b = new B(); B.foo.n // 99 A.foo.n // 99
4.Object.getPrototypeOf()
Object.getPrototypeOf The ()
method can be used to obtain the parent class from the subclass.
class Point { /*...*/ } class ColorPoint extends Point { /*...*/ } Object.getPrototypeOf(ColorPoint) === Point // true
Therefore, you can use this method to determine whether a class inherits another class.
5.super keyword
The super keyword can be used as a function or as an object
In one case, when super is called as a function, it represents the constructor of the parent class. The function of calling super is to form the this object of the subclass, and put the instance attributes and methods of the parent class on this this object.
class A { constructor() { console.log(new.target.name); } } class B extends A { constructor() { super(); } } new A(); // A new B(); // B
In the second case, when super is used as an object, in ordinary methods, it points to the prototype object of the parent class; in static methods, it points to the parent class.
class A { p() { return 2; } } class B extends A { constructor() { super(); console.log(super.p()); // 2 } } let b = new B();
In the above code, super.p() in subclass B uses super as an object. At this time, super in the ordinary object points to A.prototype, and super.p() is equivalent In A.prototype.p().
Since super points to the prototype object of the parent class, methods or attributes defined on the parent class instance cannot be called through super. As shown below:
class A { constructor() { this.p = 2; } } class B extends A { get m() { return spuer.p; } } let b = new B(); b.m // undefined
In order to solve this problem, you can define the attributes on the prototype object of the parent class
class A {}; A.prototype.x = 2; class B extends A { constructor() { super(); console.log(super.x); } } let b = new B();
ES6 stipulates that in the ordinary method of the subclass, call the parent class through super method, this inside the method points to the current subclass instance
class A { constructor() { this.x = 1; } print() { console.log(this.x); } } class B extends A { constructor() { super(); this.x = 2; } m() { super.print(); } } let b = new B(); b.m(); // 2
上面代码中,super.print()调用的是A.prototype.print(),但是此时方法内部的this指向是子类B的实例,所以输出2。
由于this指向的是子类实例,所有如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性
class A { constructor() { this.x = 1; } } class B extends A { constructor() { super(); this.x = 2; super.x = 3; console.log(super.x); //undefind console.log(this.x); // 3 } }
上面代码中,super.x
赋值为3
,这时等同于对this.x
赋值为3
。而当读取super.x
的时候,读的是A.prototype.x
,所以返回undefined
。
如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。
class Parent { static myMethod(msg) { console.log('static', msg); } myMethod(msg) { console.log('instance', msg); } } class Children extends Parent { static myMethod(msg) { super.myMthod(msg); } myMethod(msg) { super.myMethod(msg); } } Child.myMethod(1); // static 1 var child = new Child(); child.myMethod(2); // instance 2
上面代码中,super
在静态方法之中指向父类,在普通方法之中指向父类的原型对象。
另外,在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例
class A { constructor() { this.x = 1; } static print() { console.log(this.x); } } class B extends A { constructor() { super(); this.x = 2; } static m() { super.print(); } } B.x = 3; B.m() // 3
在静态方法m中,super.print指向父类的静态方法,到那时this指向的是类B,而不是B的实例。
【推荐学习:javascript高级教程】
The above is the detailed content of What is used to implement inheritance in es6. For more information, please follow other related articles on the PHP Chinese website!