TypeScript第二天基础知识
一.函数(function)
1.为函数定义类型
ts中函数的定义与js没有本质的区别,主要区别在ts中对数据的限定。
function add(a: number, b: number): number {
return a + b;
}
let myAdd = function(x: number, y: number): number { return x + y; };
let myfn=(x:number,y:number):number=>{return x+y}
如上,声明式,表达式,箭头函数都行。ts中对函数的数据量有了更严格的要求。
2.可选参数和默认参数
在ts中函数的参数可以是可选的或者具有默认值。可选参数用 ? 标记,而默认参数则在参数声明时给定一个初始值。相较于js多了一个可选参数,但js中参数的个数没什么要求,ts有了更严格的要求。
function sayHello(name: string, age?: number): void {
console.log(`Hello, ${name}! You are ${age || 'unknown'} years old.`);
}
sayHello('Alice'); // 输出 "Hello, Alice! You are unknown years old."
sayHello('Bob', 25); // 输出 "Hello, Bob! You are 25 years old."
3.剩余参数
在 TypeScript 中,可以使用剩余参数语法 … 来表示函数接受任意数量的参数,并将它们作为一个数组传递给函数。
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 输出 6
console.log(sum(4, 5, 6, 7)); // 输出 22
在js里面叫rest参数 …restArr
4.函数类型变量
在 TypeScript 中,我们可以使用函数类型变量来声明一个变量,这个变量的类型是函数类型。函数类型变量可以用来存储一个函数或者作为函数参数和返回值的类型。类似于模板的思想吧。
let myFunc: (a: number, b: number) => number;
myFunc = function(a: number, b: number): number {
return a + b;
};
相当于在写一个函数前先将函数的大致框架给写出来,如果不按照框架来就会报错,思路好像是更清晰了点。
5.使用接口封装函数变量类型
在 ts 中,我们可以使用接口来封装函数变量类型。通过接口,我们可以定义函数的参数类型和返回值类型。这个类似于什么呢,当函数类型的声明过于复杂了,我们可以使用interface在外面给它命名为更简单的名字,方便阅读。也算解耦吧。
interface MyFunc {
(a: number, b: number): number;
}
let myFunc: MyFunc = function(a: number, b: number): number {
return a + b;
};
let result = myFunc(5, 3);
console.log(result); // Output: 8
6.函数重载
ts支持函数重载,即可以为同一个函数提供多个类型签名。函数重载的目的是为了增加函数的灵活性和可用性。
function reverse(value: string): string;
function reverse(value: number): number;
function reverse(value: string | number): string | number {
if (typeof value === 'string') {
return value.split('').reverse().join('');
} else if (typeof value === 'number') {
return +value.toString().split('').reverse().join('');
}
}
console.log(reverse('hello')); // 输出 'olleh'
console.log(reverse(12345)); // 输出 54321
二.类(class)
- 类是现实世界或思维世界中的实体在计算机中的反映,它将数据(属性)以及这些数据上的操作(方法)封装在一起。
- 对象是具有类类型的变量。类和对象是面向对象编程技术中的最基本的概念。
1.类的命名
在 TypeScript 中,类(class)是用来创建对象的蓝图,它定义了对象的属性和方法。
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
let person = new Person("John", 25);
person.sayHello(); // Output: Hello, my name is John and I am 25 years old.
需要注意的是当使用类创建一个新的对象的时,只有属性是完全给了这个对象,方法还是指向的类的方法。在编码为js时就是使用了js中的原型思想来实现了类的方法不占用内存的思想。
2.对象和内存
- new多次本质上是创建了多个了对象, 只有创建了对象,才能使用对象访问对象的字段或方法;
- 对象在堆中,计算机堆中内存无名字,只能通过地址使用之,堆中对象地址通过hash后得到引用值,引用类型变量保存的就是引用值;
- 每个对象都有唯一引用, 只能通过对象的引用使用对象, new 会返回对象的引用(this);
- 当类中定义了属性,该类的每个对象都会独立开辟出属性成员,当前对象独享;
- 创建对象时,方法不会被开辟出来,同一个类的方法被所有该类对象共用(原型和原型链);
- 同一对象可被多个变量引用,当一个对象没有引用时,对象的生命就被GC(拉圾回收机制)管理了, 当对象销毁时,对象中独享的字段成员也会随之销毁;
- 只有类不能做事情,类的对象才有用, 类成员(静态成员例外);
3.this
在 TypeScript 中,this 是一个特殊的关键字,用于表示当前对象的引用。它可以在类的方法、构造函数和箭头函数中使用。跟js中的用法差不多依然是谁调用它谁就是this。在类的方法中,this 指向调用该方法的对象。
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
sayHello() {
console.log(`Hello, ${this.name}!`);
}
}
const person = new Person("Alice");
person.sayHello(); // 输出 "Hello, Alice!"
4.构造函数(constructor)
在 TypeScript 中,constructor 是一个特殊的方法,用于定义类的构造函数。构造函数在创建类的实例时被自动调用,并且用于进行初始化操作。
跟js中的构造函数思想差不多,同样是仅仅是对数据类型有了更高的要求。
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person("Alice", 25);
person.sayHello(); // 输出 "Hello, my name is Alice and I am 25 years old."
5.静态方法
在 TypeScript 中,静态方法是属于类本身而不是类的实例的方法。静态方法可以通过类名直接调用,而不需要先创建类的实例。
要声明一个静态方法,可以在方法前加上 static 关键字。
有静态的方法的同时也有静态的属性,同样在前面加上static关键字即可。
class MathUtils {
static sum(a: number, b: number): number {
return a + b;
}
}
const result = MathUtils.sum(5, 3);
console.log(result); // 输出 8
需要注意的是,静态方法不能被子类继承或覆盖。它们属于类本身,而不是类的实例。如果要在子类中使用相似的功能,可以在子类中定义一个新的静态方法。
静态方法在许多情况下非常有用,例如创建工具类或实现单例模式。它们提供了一种直接访问类的方法,无需创建类的实例。
6.存取器
在 TypeScript 中,存取器(Accessor)是一种用于定义类属性的特殊方法。它允许我们在访问和设置类属性时执行自定义的逻辑。
存取器通常由 get 和 set 关键字定义,它们分别用于获取和设置属性的值。
class Person {
private _name: string;
get name(): string {
return this._name;
}
set name(value: string) {
if (value.length > 0) {
this._name = value;
} else {
console.log("Invalid name");
}
}
}
const person = new Person();
person.name = "John";
console.log(person.name); // 输出 "John"
person.name = "";
// 控制台输出 "Invalid name"
在赋值时,set 方法会执行自定义逻辑来验证传入的值。在访问时,get 方法会返回 _name 的值。
7.继承
-
语法
class child_class_name extends parent_class_name { }
-
只能单继承(多继承会违背类本质), 一个类的父类只能有一个,但是一个类可以有多个子类。子类也可以再次被当作父类,形成树结构;
-
子类继承父类后,不会影响父类的独立使用;
-
类型上包含关系才能使用继承(同类事物才能使用继承, 如人是动物,所以人可以继承动物);
-
类中只能写本质的东西,如一个表示人的类,不能在类中写打乒乓球的方法,一个表示动物的类中不能写在水里游的方法。否则父类会侵略子类;
-
子类对象可以访问从直接和间接父类中继承下来的成员;
-
继承最原始的作用是什么?就是为了代码重用
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log("Animal is making a sound");
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log("Dog is barking");
}
}
const dog = new Dog("Buddy");
console.log(dog.name); // 输出 "Buddy"
dog.makeSound(); // 输出 "Dog is barking"
8.super
-
子类并且该子类带有构造方法,则该子类构造函数必须使用super(<实参>),不管父类是否写了构造方法;
-
super要位于构造方法中的this使用之前;
-
子类对象的创建过程:创建父类对象,然后在父类对象基础上追加子类成员得到子类对象,然后子类构造函数先执行,子类构造函数中super(<实参>)再调用父类构造函数的执行 ;
-
没有继承父类,构造函数中就不能有super(<实参>);
-
- super(父类所需参数)
如果父类和子类都有构造函数,并且父类构造函数有参数,那么要求子类构造函数 super(…)中必须为父类传参数。
-
new 创建对象时,如果类中有构造方法,则以该构造方法所需参数传参
-
new 对象时,如果类中无构造函数,并且该类又有父类,则以父类构造方法所需参数传参。(不提倡使用)
-
构造函数中的super还可以访问父类中继承下来的成员.(如果没有重写,不提倡使用)
实际上同一个类中super和this可以出现在构造函数和方法中,它们的值都是一样的,但是它们的偏移量不相同,super只管到父类对象,而this管到子类对象,而父类对象只是子类对象的一个组成部分。所以super只能访问父类的成员,而this可以访问父类和子类的成员
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name: string) {
super(name); // 调用父类的构造函数
}
}
const dog = new Dog("Buddy");
console.log(dog.name); // 输出 "Buddy"
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name: string) {
super(name); // 调用父类的构造函数
}
}
const dog = new Dog("Buddy");
console.log(dog.name); // 输出 "Buddy"
-
构造函数中的super还可以访问父类中继承下来的成员.(如果没有重写,不提倡使用)
实际上同一个类中super和this可以出现在构造函数和方法中,它们的值都是一样的,但是它们的偏移量不相同,super只管到父类对象,而this管到子类对象,而父类对象只是子类对象的一个组成部分。所以super只能访问父类的成员,而this可以访问父类和子类的成员