function
Functions are an extremely important part of JavaScript, and we’ve always called them first-class citizens, the basic building blocks of any application.
Functions
Like JavaScript, TypeScript creates named and anonymous functions.
-
There are two ways to create a function in JavaScript:
// Name the function function add(x,y){ return x + y; }; // Anonymous function let add2 = function(x,y){ return x + y; }; Copy the code
TypeScript function types
-
Annotation type
Examples of the two ways in which JavaScript can create functions are as follows:
// Name the function function add(x:number,y:number) :number{ return x + y; }; // Anonymous function let add2 = function(x:number,y:number) :number{ return x + y; }; Copy the code
You can see from the code that we can add a type to each parameter as well as to the return value.
-
Required, optional, default, and indefinite parameters
-
Required parameters
In TypeScript, the number of arguments assigned to a function must match the number of arguments the function expects to pass in, or an error will be returned
function Person(name:string,age:number){ return name + '有' + age + ', ' } let person1 = Person('jack')// Two parameters are expected, but the function only gets one let person2 = Person('jack'.18.'Play basketball')// Two parameters are expected, but the function gets three let Person3 = Person('jack'.18)//right Copy the code
-
Optional parameters
In JavaScript, each parameter in a function is optional and the user can reserve it as needed. When we need an optional parameter in TypeScript, we add a ** after the parameter we want to make optional. Is an optional parameter **.
function Person(name:string,age:number,hobby? :string){ return name + '有' + age + ', '+'like' + hobby; } let result1 = Person("Bob");// It prompts you to expect 2-3 arguments, but the function only gets one let result2 = Person("Bob".18."Play basketball");//right let result3 = Person("Bob".18);//right Copy the code
-
The default parameters
In TypeScript, we can set a value for a function parameter and assign it a value if the user does not provide a parameter or if the user passes undefined to it. We call these parameters default parameters.
function Person(name:string,age:number,hobby='Play basketball'){ return name + '有' + age + ', '+'like' + hobby; } let result1 = Person("Bob");// It prompts you to expect 2-3 arguments, but the function only gets one let result2 = Person("Bob".18."Play basketball");//right let result3 = Person("Bob".18);//right let result4 = Person("Bob".18."Play football");//right let result5 = Person("Bob".18.undefined);//right Copy the code
-
Uncertain parameters
Unlike required, optional, and default parameters, which are all discussed one parameter at a time, indefinite parameters are composed of multiple parameters as a group. In JavaScript we can use arguments for indefinite arguments, whereas in TypeScript we can use an ellipsis (…). To indicate that the parameter is an indefinite parameter.
function Person(name:string. hobby:string[]){ return name +'like' + hobby.join(' '); } let result2 = Person("Bob"."Play basketball".'Play football'.'Play badminton');//right let result3 = Person("Bob".18."Play basketball".'Play football'.'Play badminton'); // Parameters of type "number" cannot be assigned to parameters of type "string" Copy the code
-
this
Learning how to use this in JavaScript is an important skill. Since TypeScript is a superset of JavaScript, TypeScript developers also need to learn how to use this correctly in TypeScript.
-
This and the arrow function
In JavaScript, the fact that this is a variable that is set when a function is called makes it a very powerful and flexible feature, but at the expense of the execution context, which can cause this pointing problems when returning a function or passing a function as an argument, as in the following example:
let deck = { suits: ["Red heart"."Spade"."Sucks"."Square"].cards: Array(52), createCardPicker: function () { return function () { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); console.log(this);// This is undefined return { suit: this.suits[pickedSuit], card: pickedCard % 13}; }; }};let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker();'this' has an implicitly typed attribute, so the annotation does not have any type console.log("card: " + pickedCard.card + " of " + pickedCard.suit); Copy the code
We can solve the pointing problem of this by using ES6’s arrow syntax to ensure that this is bound to the correct location, as follows:
let deck = { suits: ["Red heart"."Spade"."Sucks"."Square"].cards: Array(52), createCardPicker: function () { return () = > { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return { suit: this.suits[pickedSuit], card: pickedCard % 13}; }; }};let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit); Copy the code
-
This parameter
The above example uses arrow syntax to solve the pointing problem of this, but this is still of type any. We can solve the problem by providing an explicit this argument as follows:
interface Card { suit: string; card: number; } interface Deck { suits: string[]; cards: number[]; createCardPicker(this: Deck): () = > Card; } let deck: Deck = { suits: ["Red heart"."Spade"."Sucks"."Square"].cards: Array(52), createCardPicker: function (this: Deck) { return () = > { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return { suit: this.suits[pickedSuit], card: pickedCard % 13}; }; }};let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit); Copy the code
By providing an explicit this argument, we now know that this is now a Deck type, not an any type.
overloading
Describe a function that produces different results when passed different arguments to facilitate type checking:
let suits = ["hearts"."spades"."clubs"."diamonds"];
function pickCard(x: { suit: string; card: number} []) :number;
function pickCard(x: number) :{ suit: string; card: number };
function pickCard(x: any) :any {
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13}; }}let myDeck = [
{ suit: "diamonds".card: 2 },
{ suit: "spades".card: 10 },
{ suit: "hearts".card: 4},];let pickedCard1 = myDeck[pickCard(myDeck)];
console.log("card: " + pickedCard1.card + " of " + pickedCard1.suit);
let pickedCard2 = pickCard(12);
console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);
Copy the code
This example has only two overloads: one for an object and one for a number. If the pickCard() function is called with a different type of argument, it will cause a compilation error.
class
The definition of a class
Class is the basis of information encapsulation in object-oriented programming. Class is a user-defined reference data type, also known as class type. Each class contains data descriptions and a set of functions that manipulate data or pass messages. Instances of classes are called objects.
Class properties and methods
A class can generally contain static attributes, member attributes, constructors, static methods, and member methods as follows:
class Person{
// Static attributes
static names:string = 'jack';
// Member attributes
age:string;
// constructor
constructor(message:string){
this.age = message;
};
// static function
static getName(){
return this.names
}
// Member functions
getAge(){
return `${Person.names}There are nowThe ${this.age}At the age of `}}let jackAge = new Person('16');
console.log(jackAge.getAge());
console.log(Person.getName());
Copy the code
As you can see from the above code, static members are not visible on the instance but on the class itself, which means that when we need to access the static member, we need to call the static member from the class itself.
inheritance
Inheritance means that a subclass inherits the characteristics and behaviors of its parent class, so that the subclass has the attributes and methods of its parent class. It is one of the most basic methods to extend the parent class. The code is as follows:
class Animal {
name:string;
constructor(newName:string){
this.name = newName;
}
move(distance: number = 0) {
console.log(`The ${this.name} moved ${distance}m.`); }}class Dog extends Animal {
bark() {
console.log("Woof! Woof!"); }}const dog = new Dog('Dog');
dog.move(10);
dog.bark();
console.log(dog.name);
Copy the code
ECMAScript private fields
In Typescript3.8, Typescript supports the syntax for ECMAScript private fields, as shown below:
class Person {
#name: string;
constructor(theName: string) {
this.#name = theName; }}new Person("jack").#name;
//Property '#name' is not accessible outside class 'Person' because it has a private identifier.
Copy the code
#name is declared, but its value is never read. Private fields have the following characteristics:
- Private fields start with a “#” character
- A private field only applies to the class it contains
- Private fields cannot be accessed outside of their containing classes and are not detected
Typescript private fields
Typescript also has its own method (private) to mark members as private fields, another method that cannot be accessed from outside the containing class:
class Person {
private name: string;
constructor(name: string) {
this.name = name; }}class Jack extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is The ${this.name} and I work in The ${this.department}. `;
}//Property 'name' is private and only accessible within class 'Person'
}
let howard = new Jack("Jack"."Technical Department");
console.log(howard.getElevatorPitch());
console.log(Jack.name);
console.log(Person.name)
console.log(howard.name);
//Property 'name' is private and only accessible within class 'Person'
Copy the code
There is a protected behavior in Typescript that is similar to the private behavior, except that members declared in protected can be queried by derived classes as follows:
class Person {
protected name: string;
constructor(name: string) {
this.name = name; }}class Jack extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is The ${this.name} and I work in The ${this.department}. `; }}let howard = new Jack("Jack"."Technical Department");
console.log(howard.getElevatorPitch());
console.log(Jack.name);
console.log(Person.name)
console.log(howard.name);//Property 'name' is protected and only accessible within class 'Person' and its subclasses. Only accessible in class "Person" and its subclasses.)
Copy the code
Protected When a constructor is marked, the class cannot be instantiated, but can be extended (inherited) as follows:
class Person {
protected name: string;
protected constructor(theName: string) {
this.name = theName; }}// Can be inherited
class Jack extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is The ${this.name} and I work in The ${this.department}. `; }}let howard = new Jack("Jack"."Technical Department");
let john = new Person("John");//Constructor of class 'Person' is protected and only accessible within the class declaration. Can only be accessed in class declarations.
Copy the code
Read-only modifier
In Typescrip, we use the readonly keyword to make properties read-only. Read-only properties must be initialized in their declaration or constructor as follows:
class Person {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor(theName: string) {
this.name = theName; }}let dad = new Person("jack");
console.log(dad.name);
dad.name = "jack";// Name is a read-only property and cannot be assigned
Copy the code
accessor
Getters /setters methods are supported in Typescript. By accessing members of intercepting objects, we have more control over how members are accessed on each object. This helps prevent abnormal data.
let nameMaxLength = 8;
class Person {
private _name: string;
constructor(newName:string){
this._name = newName;
}
get name() :string {
return this._name;
};
set name(newName: string) {
if (newName && newName.length > nameMaxLength) {
console.log('Names cannot be longer than '+ nameMaxLength);
return;
}
this._name = newName; }}let Jack = new Person('Jack');
Jack.name = 'JackWangs';
if(Jack.name){
console.log(Jack.name);
}
Copy the code
An abstract class
An abstract class is a base class that can be derived from other classes. An abstract class cannot be instantiated. Unlike interfaces, abstract classes may contain implementation details for other members. Typically, we use the abstract keyword declaration to define abstract classes as follows:
abstract class Animal{
name:string;
constructor(newName:string){
this.name = newName;
}
abstract move(distance:number) :void
}
let dog = new Animal();//error:Cannot create an instance of an abstract class
Copy the code
Since an abstract class cannot be instantiated directly, we can invoke properties and methods of the abstract class by instantiating a subclass of the abstract class as follows:
abstract class Animal{
name:string;
constructor(newName:string){
this.name = newName;
}
abstract move(distance:number) :void
}
class Dogs extends Animal {
constructor(name: string) {
super(name);
}
move(distance: number) :void {
console.log(`The ${this.name} moved ${distance}m`); }}let dog = new Dogs('dog');
dog.move(10);
Copy the code
Class method overloading
Class method overloading and function overloading work in much the same way, with the following code:
class Animal{
getID():void;
getID(id: number) :void;
getID(id? :number){
if(typeof id==="number") {console.log('gets the ID as${id}Of animal species);
}else{
console.log('Get all animal species'); }}}let dog = new Animal();
dog.getID(10);//" Get animal species with id 10"
dog.getID()//" Get all animal species"
Copy the code
Use classes as interfaces
A class declaration creates two things: a type that represents an instance of the class and a constructor. Since classes create types, they can be used where interfaces can be used, as follows:
class Person{
name:string;
age:number
}
interface Person2 extends Person{
hobby:string
}
let jack:Person2={name:'jack'.age:19.hobby:'Play basketball'};
function person(msg:Person2){
console.log(msg);
}
person(jack);//{"name": "jack","age": 19,"hobby": "basketball "}
Copy the code