Use prototypes to implement various syntaxes of Class

I have never paid enough attention to Class before. The usual use of prototypes is limited to hanging properties on the prototype of the constructor. There is no need for a prototype, not to mention that your Class is just a syntactic sugar for the prototype?

Until the company started a webgis project using openlayers. After looking at the code of openlayers, the entire API is built using Class. I just realized that the use of Class has become very common, and many libraries are built based on Class, so I must study it clearly.

This is what I think, first understand the prototype, then understand the Class, and finally practice it and restore the various grammars of the Class using the prototype. In this way, you will be able to master the object-oriented thinking of JS well.

1. Review the prototype of the object

For a programming language, it is a basic requirement to abstract the same type of things into a data structure and use it as a template to create instances. This is the object-oriented idea.

JS was designed as an object-oriented language from the beginning. It uses constructors as “templates” to generate objects. For example:

1

2

3

4

5

6

7

8

9

10

11

function Student(name, age) {

this.name = name;

this.age = age;

this.say = function(intro) {

console.log(intro);

}

}

let xiaohong = new Student('小红' , 14);

let xiaoming = new Student('Xiao Ming', 15);

xiaohong.say('I am Xiaohong, I like watching movies'); //I am Xiaohong, I like watching movies

xiaoming.say('I am Xiaoming, I like Xiaohong'); //I am Xiaoming, I like Xiaohong

What is the difference between constructors and ordinary functions in JS?

In fact, any ordinary function called through the new operator can be called a constructor. The special thing about the constructor is that there is an extra this in it. This this is the object returned by the constructor. There is no this in an ordinary function, and what you get by calling new is an empty object, which has no meaning.

Now, the same kind of thing – students can be easily generated via constructors. They all have names and ages, but they are all different.

However, there are some things that they all have in common, that they share. For example, their classes are all in Grade 2 of Grade 3, and their class teacher is Jay Chou. How to express this relationship?

This is prototype, which is prototype.

In JS, all functions have a prototype attribute. This is an object with only one attribute by default: constructor, which points to the constructor itself. In other words, the constructor and prototype refer to each other through prototype and construcotr.

All objects generated through the constructor share this prototype object.

1

2

3

4

5

6

7

8

9

10

function Student(name, age) {

this.name = name;

this.age = age;

}

Student.prototype.className = 'Class Two of Three Years';

Student.prototype.teacher = 'Jay Chou';

let xiaohong = new Student('小红' , 14);

let xiaoming = new Student('Xiao Ming', 15);

console.log(xiaohong.className, xiaohong.teacher); //Grade 2, Jay Chou

console.log(xiaoming.className, xiaoming.teacher); //Grade 2, Jay Chou

Now, we have constructors, prototypes, objects. What is their relationship?

The constructor is the link between the prototype and the object, and is responsible for giving birth to the “child”, which is the object, for the “mother” of the prototype. The things in the prototype are the same for all children, such as country and skin color. The things in the constructor can be personalized by children, such as appearance and height.

Maybe you have also heard of constructor and __proto__, what do they do? Very simply, they exist just to allow constructors, prototypes, and objects to reference each other.

function Student(name, age) {
    this.name = name;
    this.age = age;
}
let xiaohong = new Student('小红', 14);
console.log(Student.prototype); //{constructor: Student}
console.log(Student.prototype.constructor === Student); //true
console.log(xiaohong.__proto__ === Student.prototype); //true
console.log(xiaohong.constructor === Student); //true

Through ===, we can know that there is indeed a mutual reference relationship between them, not just a wait-and-see relationship.

2. Use prototypes to implement various grammars of Class

Next, we use prototype writing to restore the various grammars of Class.

(1) Constructor (instance attributes and methods)

1

2

3

4

5

6

7

8

9

10

11

12

//Class syntax

class Student {

constructor(name, age) {

this.name = name;

this.age = age;

}

}

//Prototype syntax

function Student(name, age) {

this.name = name;

this.age = age;

}

(2) Prototype attributes and methods

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//Class syntax

class Student {

teacher = 'Jay Chou';

say() {

console.log('Listen carefully!');

}

}

//Prototype syntax

function Student() {}

Student.prototype.teacher = 'Jay Chou';

Student.prototype.say = function() {

console.log('Listen carefully!');

};

let xiaohong = new Student();

console.log(xiaohong.teacher); //Jay Chou

xiaohong.say(); //Listen carefully!

(3) Static properties and methods

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

//Class syntax

class Student {

static teacher = 'Jay Chou';

static say() {

console.log('Listen carefully!');

}

}

//Prototype syntax

function Student() {}

Student.teacher = 'Jay Chou';

Student.say = function() {

console.log('Listen carefully!');

};

console.log(Student.teacher); //Jay Chou

Student.say(); //Listen carefully!

(4) Inheritance

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

twenty one

twenty two

twenty three

twenty four

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

//Class syntax

class Person {

constructor(name) {

this.name = name;

}

say() {

console.log('I can speak');

}

static think() {

console.log('Humans can think');

}

}

class Student extends Person {

constructor(name, school) {

super(name);

this.school = school;

}

study() {

console.log('I want to go to school');

}

}

let xiaohong = new Student('小红' , 'Eleven School');

//Prototype syntax

function Person(name) {

this.name = name;

}

Person.prototype.say = function() {

console.log('I can speak');

}

Person.think = function() {

console.log('Humans can think');

}

function Student(school) {

this.school = school;

}

Student.prototype = new Person('小红');

Student.prototype.constructor = Student;

Student.prototype.study = function() {

console.log('I want to go to school');

};

Object.setPrototypeOf(Student, Person);

let xiaohong = new Student('Eleven School');

console.log(xiaohong.name); //小红

console.log(xiaohong.school); //Eleventh School

xiaohong.say(); //I can speak

xiaohong.study(); //I want to go to school

Student.think(); //Humans can think

It can be seen that, especially in terms of inheritance syntax, Class is much simpler than prototype.

In general, as the syntactic sugar of prototypes, Class not only has clearer semantics and is easier to understand, but it is also simpler to write. So, happily use Class from now on!

My level is very limited, and I write mainly to clarify what I have learned. If there are any errors, please correct me, I would be grateful.