The Understanding of ES6 class Class

Posted by opido on Wed, 28 Aug 2019 11:33:34 +0200

Advantage

The ES6 class provides several obvious benefits:

Compatible with the current large amount of code.
Classes make it easier for beginners to get started than constructors and constructor inheritance.
Subclassification is supported at the linguistic level.
Built-in constructors can be subclassed.
There is no need for inheritance libraries; code between frameworks becomes more portable.
It lays the foundation for future advanced features: traits (or mixins), immutable instances, and so on.
Enables tools to analyze code statically (IDE, type detector, code style detector, etc.).

shortcoming

ES6 obscures the essence of JavaScript inheritance.
Classes will imprison you because of compulsory new.

Traditional Classes

function Point(x, y){
      this.x = x;
    this.y = y;
}
Point.prototype.toString = function(){
    return "(" + this.x + "," + this.y + ")";
}
const p = new Point(1,2);
console.log(p);//Point {x: 1, y: 2}
console.log(p.toString());//(1,2)

The class of ES6 is equivalent to grammatical sugar.

The above code is written with a change to class

class Points {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString(){
        return '(' + this.x + ',' + this.y + ')';            }
}
const ps = new Points(1, 2);
console.log(ps);//Points {x: 1, y: 2}
console.log(ps.toString());//(1,2)

Classes of ES6 can be seen as another way to write constructors

class Cty{
    //....
}
console.log(typeof Cty);//function
console.log(Cty === Cty.prototype.constructor);//true
//The data type of a class is a function, and the class itself points to the constructor.

When you use it, you also use the new command directly on the class, which is exactly the same as the use of the constructor.

class Bar {
    doStuff(){
        console.log('stuff');
    }
}
const b =new Bar();
b.doStuff();//stuff

The method above the instance of a class is actually calling the method on the prototype.

class B {};
const BS = new B();
console.log(BS.constructor === B.prototype.constructor);//true

Classes and Subclasses

class Poin{
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    toString(){
        return `(${this.x},${this.y})`;
    }
}
class ColorPoin extends Poin{
    constructor(x,y,color){
        super(x,y);
        this.color = color;
    }
    toString(){
        return super.toString() + " in " + this. color;
    }
}
// type
console.log(typeof Poin);//function
//news Instance
const cp = new ColorPoin(25,8,'green');
console.log(cp.toString());//(25,8) in green
console.log(cp instanceof ColorPoin);//true
console.log(cp instanceof Poin);//true
// instanceof tests whether the prototype attribute of the constructor appears anywhere in the prototype chain of the object

Here are some methods:

Object.assign method can easily add more than one method to an image class at a time

class ObjAssign {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
}
Object.assign(ObjAssign.prototype,{
    toString(){
        console.log("string");
    },
    toValue(){
        console.log("value")
         }
})
const Obj = new ObjAssign('Bob',24);
console.log(Obj);
Obj.toString();//string
Obj.toValue();//value
console.log(Object.keys(ObjAssign.prototype));//["toString", "toValue"]
console.log(Object.getOwnPropertyNames(ObjAssign.prototype));// ["constructor", "toString", "toValue"]

Instances of classes

 class Pott {
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    toString() {
        return '(' + this.x + ',' + this.y + ')';
    }
}
const pott = new Pott(2,3);
pott.toString();
console.log(pott.hasOwnProperty("x"));//true
console.log(pott.hasOwnProperty("y"));//true
console.log(pott.hasOwnProperty("toString"));//false
console.log(pott);
console.log(pott.__proto__);
console.log(pott.__proto__.hasOwnProperty("toString"));//true

const p1 = new Pott(2,3);
const p2 = new Pott(3,3);

console.log(p1.__proto__ === p2.__proto__);//true

p1.__proto__.printName = function(){
    return "Oops";
}
console.log(p1.printName());//Oops
console.log(p2.printName());//Oops
const p3 = new Pott(4,2);
console.log(p3.printName());//Oops

getter and setter

The prop attribute has corresponding storage function and value function.

class MyClass {
   constructor(){
        //...
    }
    get prop(){
        return 'getter';
    }
    set prop(value){
        console.log("setter:" + value);
    }
}
const inst = new MyClass();
inst.prop = 123;//setter: 123
console.log(inst.prop)//getter

Storage and value functions are set on the Descriptor object of the attribute.

class CustomHTMLElement {
   constructor(element) {
        this.element = element;
    }

    get html() {
        return this.element.innerHTML;
    }

    set html(value) {
        this.element.innerHTML = value;
    }
}

const descriptor = Object.getOwnPropertyDescriptor(
    CustomHTMLElement.prototype, "html"
);

console.log("get" in descriptor)  // true
console.log("set" in descriptor)  // true

calss expression

const MyCl = class Me {
    getClassName() {
        return Me.name;
    }
}
const inMe = new MyCl();
console.log(inMe.getClassName());//Me is defined only within the class

Instance of person immediate execution

const person = new class{
    constructor(name){
        this.name = name;
    }
    sayName(){
        console.log(this.name);
    }
}('Zhang San');
person.sayName();//Zhang San

class name attribute

class Mine {
//...
}
console.log(Mine.name);//Mine

The Direction Problem of class this

this.printName = this.printName.bind(this) binding solution

class Logger{
   constructor(){
        this.printName = this.printName.bind(this);
    }
    printName(name = 'there'){
        this.print(`Hello ${name}`);
    }
    print(text){
        console.log(text);
    }
}
const logger = new Logger();
const {printName} = logger;
printName();//Hello there

Static method static

If a method is preceded by a static keyword, it means that the method is not inherited by an instance, but invoked by a class.

class Foo{
    static classMethod() {
        return 'hello';
    }
}
console.log(Foo.classMethod());//Hello

const foo = new Foo();
// console.log(foo.classMethod())//foo.classMethod is not a function
class Fun {
   static bar(){
       this.baz();
   }
   static baz(){
       console.log('hello');
   }
   baz(){
       console.log('world');
   }
}
Fun.bar();//hello

Static methods of parent classes can be called by subclasses

class Func{
   static classMethod() {
        return 'hello';
    }
}
class Baa extends Func{
    static classMethod(){
        console.log(super.classMethod + ",too") ;
    }
}
Baa.classMethod();//hello,too

New Writing of Instance Attributes

class IncreasingCounter{
    // constructor(){
    //     this._count = 0;
    // }
    _count = 0;
    get value(){
        console.log('getting the current value');  
        return this._count;           
    }
    increment(){
        this._count++;
    }
}

new.target attribute

Ensure that functions can only be invoked through the new command

function PersonMan(name){
    if(new.target !== undefined){
        this.name = name;
    }else{
        throw new Error('Must be used new Command generation instance')
    }
}
function PersonWoman(name){
    if(new.target === PersonWoman){
        this.name = name;
    }else{
        throw new Error('Must be used new Command generation instance')
    }
}
const personman = new PersonMan('Zhang San');
const personwoman = new PersonWoman('Zhang San');
// Const personwoman2 = PersonWoman. call (PersonWoman,'Zhang San'); //Error reporting

An internal call to new.target returns the current class

class Rectangle{
    constructor(length,width){
        console.log(new.target);
        console.log(new.target===Rectangle);
        this.length = length;
        this.width = width;
    }
}
const rectangle = new Rectangle(3,4);

When a subclass inherits a parent class, new.target returns a subclass

class Rec{
   constructor(length,width){
        console.log(new.target);
        console.log(new.target===Rectangle);
        console.log(new.target===Square);
        this.length = length;
        this.width = width;
        //...
    }
}
class Square extends Rec{
    constructor(length,width){
        super(length,width);
    }
}
const squareA = new Square(3,6);//false/true

Reference Articles
Exploring ES6
ES6 Ruan Yifeng

Topics: Javascript Attribute