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