preface

JavaScript does not have the concept of classes, unlike other traditional strongly typed languages, such as Java, JS classes (constructors) are fundamentally different in design. Java classes are copies of code, while JS uses prototype chain inheritance. The so-called constructors are just ordinary functions. (It’s just that capitalizing is the norm.)

ES6 classes are essentially syntax-candy for constructors, except that the syntax-candy is written more like Java. For the sake of distinction, I will devote this blog post to comparing class and ES5 constructors

Sets the instance object’s own properties

Constructor notation

Through the constructor, we can understand the prototype chain design principle of JS, the following is the basic use of the constructor

function Person(name,age){
   this.name=name
   this.age=age
}
const p=new Person('jack'.23)
Copy the code

The class writing

class Person{
   constructor(name,age){
      this.name=name
      this.age=age
   }
}
const p=new Person('jack'.23)
Copy the code

Sets the common methods of the instance object

Constructor notation

Person.prototype={
   constructor:Person,
   fn1(){},
   fn2(){}}Copy the code

The class writing

class Person{
   constructor(name,age){... };fn1(){};
   fn2(){};
}
Copy the code

The own method that sets the instance object

Constructor notation

function Person(name,age){...this.saiHi=function(){console.log(this.name)}
}
Copy the code

The class writing

class Person{
    name=' ';
    age=' ';
   constructor(name,age){... };fn1(){};/ / on the prototype
   fn2(){};
   sayHi=function(){console.log(this.name)} / / their own
}
Copy the code

Set the constructor static properties

A constructor’s static property means that the constructor itself can access it

Constructor notation

Person.prop1='staticProp1'
Person.prop2='staticProp2'
Copy the code

The class writing

class Person{
   static prop1='staticProp1'
   static prop2='staticProp2'
   constructor(name,age){... };fn1(){};/ / on the prototype
   fn2(){};
   sayHi=function(){console.log(this.name)} / / their own
}
Copy the code

Set the constructor static method

Constructor notation

Person.staticFn=function (){}
Copy the code

The class writing

class Person{...static staticFn=function(){}
   constructor(name,age){... }; . }Copy the code

Set the constructor’s private field

Constructor notation

function Person(name,age){
   let _selfName='123456' // The constructor is private and cannot be accessed directly from outside
   let _selfFn=() = >{return _selfName} // The constructor is private and cannot be accessed directly from outside
   this.saiHi=function(){console.log(_selfFn())} // The instance's own method
}
Copy the code

Variable names are preceded by _, which is a dev-defined way to distinguish between private fields

The class writing

class Person{
   #selfName='123456'
   #selfFn=() = >{return this.#selfName}
   constructor(name,age){... }; sayHi=function(){console.log(this.#selfFn())}
Copy the code

The class notation is defined by the # keyword and this if you want to access it

Since private fields cannot be accessed directly, the sayHi method is used instead.

summary

Constructor notation

function Person(name,age){
   let _selfName='123456' // The constructor is private and cannot be accessed directly from outside
   let _selfFn=() = >{return _selfName} // The constructor is private and cannot be accessed directly from outside
   this.name=name // The instance's own properties
   this.age=age
   this.saiHi=function(){console.log(_selfFn())} // The instance's own method
}
Person.prototype={ // The common method of the instance
   constructor:Person,
   fn1(){},
   fn2(){}
}
Person.prop1='staticProp1' // The constructor's own property
Person.prop2='staticProp2'
Person.staticFn=function (){} // The constructor's own method
const p=new Person('jack'.23)
Copy the code

The class writing

class Person{
    name=' ';// You can also write instance attributes here
    age=' ';
   static prop1='staticProp1'// The constructor's own property
   static prop2='staticProp2'
   #selfName='123456'// The constructor is private and cannot be accessed directly from outside
   #selfFn=() = >{return this.#selfName}// The constructor is private and cannot be accessed directly from outside
   constructor(name,age){
      this.name=name// The instance's own properties
      this.age=age// The instance's own properties
   };
   fn1(){};// The common method of the instance
   fn2(){};// The common method of the instance
   sayHi=function(){console.log(this.#selfFn())}// The constructor's own method
}
const p=new Person('jack'.23)
Copy the code

inheritance

Constructor notation

The constructor approach can be implemented in two steps.

The first step is to call the parent class’s constructor in the subclass’s constructor.

function Super(name){
   this.name=name
}
function Sub(name,age){
   Super.call(this,name)
   this.age=age
}
Copy the code

In the code above, Sub is the constructor of a subclass, and this is an instance of a subclass. Calling the superclass constructor Super on the instance gives the subclass instance the properties of the superclass instance.

The second step is to make the stereotype of the subclass point to the stereotype of the parent class so that the subclass can inherit the stereotype of the parent class.

Super.prototype.sayHi=function (){console.log('hi')}
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;// This is a good idea
Copy the code

Prototype = super. prototype; this is also useful, but is equivalent to two constructors sharing the same prototype. If you change the prototype of either Sub or Super later, it will affect both.

The best way to do this is to modify the child constructor’s prototype directly using object.create, so that __proto__ of the child constructor is attached to the parent constructor’s prototype.

The class writing

class Person{
    name;
    age;
    constructor(name,age){
        this.name=name
        this.age=age
    }
    sayHi(){
        console.log(this.name)
    }
}
class Man extends Person{
    constructor(name,age,prop){
        super(name,age)// call here
        this.prop=prop
    }
}
const a=new Man('qiuyanxi'.20.'handsome')
Copy the code

The class form is very handy, and now a subclass can use its parent’s methods without having to associate the subclass with its parent’s prototype chain. The extends keyword does the job for us

Man.prototype.__proto__===Person.prototype //true
Man.__proto__ ===Person //true // Note that this is implemented automatically by class
Copy the code

The class method has one more relationship than the ES5 method. The ES5 method does not associate the __proto__ of a subclass with its parent class, whereas the class method does this automatically. Object. SetPrototypeOf (Man,Person) associations can also be used if ES5 wants to implement them

// The traditional ES5 inherits the manual shift
/ / the original
Sub.__proto__ ===> Function.protoyype
Super.__proto__ ===> Function.protoyype
// After using Object.setProtoTypeof (Sub,Super)
Sub.__proto__ ===>Super===>Super.__proto__===>Function.prototype
Sub.prototype = object.create (super.prototype);
Sub.prototype.__proto__ ===> Super.prototype
Copy the code

conclusion

Class syntax from the future, more new friends may be very like, this is also very consistent with the JAVA class students, but the difference between Js and JAVA is still quite big, or suggest to be able to practice on the basis of class, understand the working principle of the constructor, This will help us better understand Js, an imperfect but excellent language

Reference documentation

Wangdoc.com/javascript/…

Wangdoc.com/es6/class-e…

Developer.mozilla.org/zh-CN/docs/…