[TOC]

The class was introduced in this chapter, and I hope you can review the basics of constructors, prototypes, and prototype chains in the previous chapter

Classes in TypeScript

1. Here’s an example:

class Persons {
  name: any;
  age: number | undefined;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  getName(): void {
    console.log(`${this.name}Already this year${this.age}At the age of `); }}let p11 = new Persons("za".123);
console.log(p11.getName()); // Za is 123 years old
Copy the code
  • After converting to ES5 code:
var Persons = /** @class */ (function() {
  function Persons(name, age) {
    this.name = name;
    this.age = age;
  }
  Persons.prototype.getName = function() {
    console.log(
      this.name + "\u4ECA\u5E74\u5DF2\u7ECF" + this.age + "\u5C81\u4E86"
    );
  };
  returnPersons; }) ();var p11 = new Persons("za".123);
console.log(p11.getName()); // Za is 123 years old
Copy the code

2. There are some differences here compared to when we use class in Es6

// The class definition in javascript
class An {
  constructor(name) {
    this.name = name;
  }
  getName() {
    console.log(this.name); }}var a = new An("zz");
a.getName(); // zz
Copy the code

3. The difference is that we need to define the types of data parameters passed in the constructor constructor

Class inheritance in TypeScript

class Animal {
  name: string | undefined;
  food: string;
  constructor(name: string, food: string) {
    this.name = name;
    this.food = food;
  }
  eat() {
    console.log(`${this.name}eat${this.food}`); }}class Cat extends Animal {
  constructor(name: string, food: string) {
    super(name, food);
  }
  jump() {
    console.log(`${this.name}Dancing the `); }}let xiaohhua = new Cat("xiaohua"."Cat food");
console.log(xiaohhua.eat()); // Xiaohua eats cat food
console.log(xiaohhua.jump()); // Xiaohua is jumping
Copy the code

This is basically the same as class inheritance in ES6, right

Public, private, and protected TypeScript modifiers

Here modifiers are definitions of the types of properties and methods in a class

3-1. Public for attributes

If the class core is not defined, the default type is public

class Animals {
  public name: string | undefined;
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name}Wow `); }}Copy the code

Convert to ES5 code

"use strict";
var Animals = /** @class */ (function() {
  function Animals(name) {
    this.name = name;
  }
  Animals.prototype.eat = function() {
    console.log(this.name + "\u54C7");
  };
  returnAnimals; }) ();// Same as before
Copy the code

3-2. Attribute private

When a member is marked private, it cannot be accessed outside the class in which it is declared

class Animal2 {
  private name: string | undefined;
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name}Wow `); }}var a = new Animal2("private");
a.name = "123"; The name attribute can only be used inside Animal2
new Animal2("private").name = "432"; Property "name" is private and can only be accessed in class "Animal2".
Copy the code

3-3. Protected properties

When a member is marked protected, it cannot be accessed outside the class in which it is declared, but subclasses of that class can

class Person2 {
  protected name: string;
  constructor(name: string) {
    this.name = name; }}class exPerson extends Person2 {
  public age: number;
  constructor(age: number, name: string) {
    super(name);
    this.age = age;
    this.name = name;
  }
  public getInfo() {
    console.log(`${this.name}Ha ha ha ha${this.age}`); }}let ps = new exPerson(123."za"); // Derived classes can inherit the protected property, however

ps.name = "zz"; // An error was reported
console.log(ps); // { name: 'za', age: 123 }
Copy the code

Constructors can also be protected

class Person22 {
  protected name: string;
  protected constructor(name: string) {
    this.name = name; }}class exPerson2 extends Person2 {
  public age: number;
  constructor(age: number, name: string) {
    super(name);
    this.age = age;
    this.name = name;
  }
  public getInfo() {
    console.log(`${this.name}Ha ha ha ha${this.age}`); }}let exp = new exPerson2(21."exp-name");
let per22 = new Person22("zs"); The constructor for the error class "Person22" is protected and can only be accessed in the class declaration
Copy the code

3-4. Readonly modifier

Use the readonly keyword to make the property read-only. Read-only attributes must be initialized at declaration time or in a constructor

class octPers {
  readonly name: string;
  readonly age: number = 8;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age; }}let ns = new octPers("zz".123);
console.log("- 1", ns);
ns.age = 456; // Error Cannot assign to 'age' because it is a read-only property.
console.log("- 2", ns); // What is executed here?
Copy the code

Static methods in TypeScript

A static method defines a method directly on a constructor object. Only the constructor itself can use it, and nothing else (including its derived classes) can use it.

class staticPerson {
  public name: string;
  public age: number = 8;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  static getName1() {
    console.log("---static-getName---".this);
  }
  protected getName(): void {
    console.log("---protected-getName---".this); }}let ress = new staticPerson("zzs".123);
console.log("---instancing getName", staticPerson.getName1()); The property "getName" is protected and can only be accessed in the class "staticPerson" and its subclasses.
Copy the code

Inheritance and polymorphism in TypeScript

In fact, this is more JS inheritance and polymorphism, we take ES5 and ES6 respectively on inheritance and polymorphism contrast

5-1 How is inheritance implemented in ES5?

So let’s think about inheritance. What is inheritance? How to inherit? Why inherit?

5 minus 1 minus 1 through class inheritance

The core of the class approach is that the prototype of a subclass points to an instance of the parent class. In this way, the __proto__ of the subclass instance points to the prototype of the subclass, whereas the prototype of the subclass is assigned to the instance of the parent class. Let’s make a simple diagram to illustrate how inheritance is implemented here.

var SuperClass = function(name) {
	var id = 1;
	this.name = name;
	this.work = function() {
		console.log(this.name + 'in SuperClass');
	};
};
SuperClass.prototype.getSuperName = function() {
	return this.name;
};

var SubClass = function() {
	this.getSubName = function() {
		console.log('this is subname');
	};
};

SubClass.prototype = new SuperClass('superClass');
var sub = new SubClass();

// Are there disadvantages to this? Of course there is. Let's use an example to illustrate
Copy the code

The disadvantages of this method of inheritance,

var SuperClass = function(name) {
	var id = 1;
	this.name = name;
	this.todo = [1.2.3.4];
	this.work = function() {
		console.log(this.name + 'in SuperClass');
	};
};
SuperClass.prototype.getSuperName = function() {
	return this.name;
};

var SubClass = function() {
	this.getSubName = function() {
		console.log('this is subname');
	};
};

SubClass.prototype = new SuperClass('superClass');
var sub = new SubClass();
sub.todo.push('subClass name');
var sub2 = new SubClass();
console.log(sub2.todo); // [ 1, 2, 3, 4, 'subClass name']
// The superclass attribute is contaminated by the instance subclass

console.log(sub.name); //superClass
console.log(sub2.name); //superClass

// An instance of a subclass can have only one name, which is obviously not flexible enough
Copy the code

Here, because subclass instance object 1 has modified the common attributes of the parent class, the corresponding attributes of subclass instance object 2 are polluted. Is there any way to avoid this kind of pollution? Of course there is, and we’ll talk about that later.

5-1-2 inherits by the constructor
// Declare the parent class
function Animal(color) {
	this.name = 'animal';
	this.type = ['pig'.'cat'];
	this.color = color;
}

// Add a prototype method
Animal.prototype.eat = function(food) {
	console.log(food);
};

// Declare subclasses
function Dog() {
	Animal.apply(this.arguments);
	// This step is to change the context of the Animal method and give Dog the properties and methods in the parent constructor
}

var dog1 = new Dog('blue'); // dog1.color -> blue
var dog2 = new Dog('red'); // dog2.color -> red

dog1.type.push('haha');
console.log(dog2.type); // [ 'pig', 'cat' ]
Copy the code

I don’t see dog1 modifying the type attribute inherited from the parent class, but dog2’s type attribute is not affected. The reason is that when we instantiate, the Pointers to the created instance object point to different positions, so the corresponding __proto__ points to a different prototype of the subclass constructor. It can be tricky, but the essence of the new operation is that it generates two different objects, each with its own stereotype properties, that do not interfere with each other.

However, there is a drawback that subclasses cannot inherit methods and attributes from their parent class

The smart front-end developers thought of combining the advantages of the first two and carried out combinatorial inheritance.

5-1-3 Combined inheritance
// Declare the parent class
function Animal(color) {
	this.name = 'animal';
	this.type = ['pig'.'cat'];
	this.color = color;
}

// Add a prototype method
Animal.prototype.eat = function(food) {
	console.log(food);
};

// Declare subclasses
function Dog() {
	Animal.apply(this.arguments);
	// This step is to change the context of Animal's method and make Dog have it too
	// Attributes and methods in the parent constructor
}
Dog.prototype = new Animal('Animal Color');

var dog1 = new Dog();
console.log((dog1.color = 'dog1.name'));
var dog2 = new Dog();

console.log(dog2.color); // undefinedWhy is dog2.color hereundefinedRather than'dog1.name'? The constructor of our subclass already inherits the properties and methods inside the constructor of its parent class, and when instantiating our subclass, the instance object of the subclass will first look for the color property in its own object. When a corresponding property is found, regardless of whether it has a value, the property of the instantiated object itself is preferentially returned, rather than having to look up the corresponding property in the stereotype chain.Copy the code

5-2 How is inheritance implemented in ES6?

So let’s think about inheritance. What is inheritance? How to inherit? Why inherit?

5-2-1 Inheritance modes of the ES6
class Animal {
	constructor(name) {
		this.name = name;
	}
	eat(food) {
		console.log(`The ${this.name}eat${food}`); }}class Dog extends Animal {
	constructor(name) {
		super(name);
		this.name = name;
	}
	run() {
		console.log(Puppy Bubble Run); }}let dog1 = new Dog('dog');
let dog2 = new Dog('flower');
console.log(dog1.name); / / the dog
console.log(dog2.name); / / flower

dog1.__proto__ === Dog.prototype	// true
Dog.__proto__ === Animal			// trueHere Dog's __proto__ refers to the Animal class because the Animal classconstructorThe original constructor. The rest of the methods and properties are prototype public methods and properties. Can be inherited by subclassesCopy the code

Six, summarized

Here the whole article also summarizes the principle of JS inheritance and some of the problems we may ignore at ordinary times, here is equivalent to learning TS before, with everyone to review again. Well, that’s all for this article.


The Front End Road – TypeScript (4) class