06 类
loyalvi Lv7

06 类

    • 构造函数
    • 静态方法
    • 实例方法
    • 继承
    • super

class

在 JavaScript 中,class 是 ES6(ECMAScript 2015)引入的一个语法糖,用于更简洁地创建对象和实现面向对象的编程。尽管 JavaScript 本质上是基于原型继承的,class 语法提供了一种更接近传统面向对象语言的类的写法,使得代码更易于理解和维护。

基本语法

定义类

使用 class 关键字定义一个类,类的名称通常首字母大写,以区分普通变量和函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person {
// 构造函数,用于初始化类的实例
constructor(name, age) {
this.name = name;
this.age = age;
}
// 实例方法
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
// 静态方法
static sayHello() {
console.log('Hello from Person class');
}
}

创建实例

使用 new 关键字创建类的实例。

1
2
3
4
const person1 = new Person('Kimi', 25);
person1.greet(); // Hello, my name is Kimi and I am 25 years old.
const person2 = new Person('Moonshot', 30);
person2.greet(); // Hello, my name is Moonshot and I am 30 years old.

调用静态方法

静态方法可以通过类名直接调用,不需要创建实例。

1
Person.sayHello(); // Hello from Person class

类的继承

ES6 的类支持继承,可以使用 extends 关键字继承一个父类,并使用 super 关键字调用父类的构造函数和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类的构造函数
this.breed = breed;
}
makeSound() {
console.log(`${this.name} barks.`);
}
static sayHello() {
console.log('Hello from Dog class');
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
dog.makeSound(); // Buddy barks.
Dog.sayHello(); // Hello from Dog class

类的特性

  • 构造函数(Constructor):用于初始化类的实例。每个类只能有一个构造函数,如果有多个构造函数会抛出错误。
  • 实例方法:定义在类中的方法,可以通过类的实例调用。
  • 静态方法(Static Methods):定义在类上的方法,可以通过类名直接调用,不需要创建实例。
  • 继承(Inheritance):子类可以继承父类的属性和方法,并可以重写父类的方法。
  • super 关键字:用于调用父类的构造函数和方法,只能在子类的构造函数和方法中使用。

注意事项

  • 类的声明不会被提升,因此必须先声明类,然后才能使用它。
  • 类中的方法默认是不可枚举的,与对象字面量中的方法不同。
  • 类的静态方法不能通过实例调用,只能通过类名调用。

示例:一个完整的类和继承示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
static sayHello() {
console.log('Hello from Person class');
}
}
class Employee extends Person {
constructor(name, age, jobTitle) {
super(name, age); // 调用父类的构造函数
this.jobTitle = jobTitle;
}
greet() {
super.greet(); // 调用父类的 greet 方法
console.log(`I am a ${this.jobTitle}.`);
}
static sayHello() {
console.log('Hello from Employee class');
}
}
const employee = new Employee('Kimi', 25, 'Software Engineer');
employee.greet(); // Hello, my name is Kimi and I am 25 years old. I am a Software Engineer.
Employee.sayHello(); // Hello from Employee class

通过使用 class 语法,JavaScript 的面向对象编程变得更加简洁和直观,同时也提供了更强大的功能,如继承和静态方法等。

ts 和 es6 的 class 区别

TypeScript(TS)和 ES6(ECMAScript 2015)都引入了类(class)的概念,但它们在实现和功能上有一些关键区别。TypeScript 是 JavaScript 的一个超集,它在 ES6 的基础上添加了类型系统和其他一些特性。以下是 TypeScript 和 ES6 类的主要区别:

1. 类型系统

  • ES6:ES6 的类不支持类型注解,所有变量和方法都是动态类型的。
  • TypeScript:TypeScript 的类支持类型注解,可以在类的属性和方法参数上指定类型,这有助于在编译时进行类型检查,减少运行时错误。

示例

1
2
3
4
5
6
7
8
9
10
11
12
// ES6 类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('Kimi', 25);
person.greet(); // Hello, my name is Kimi and I am 25 years old.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// TypeScript 类
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): void {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('Kimi', 25);
person.greet(); // Hello, my name is Kimi and I am 25 years old.

2. 访问修饰符

  • ES6:ES6 的类不支持访问修饰符(如 publicprivateprotected)。
  • TypeScript:TypeScript 支持访问修饰符,可以明确指定类的属性和方法的访问权限。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person {
public name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public greet(): void {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
private getAge(): number {
return this.age;
}
}
const person = new Person('Kimi', 25);
person.greet(); // Hello, my name is Kimi and I am 25 years old.
// person.getAge(); // 抛出错误:Property 'getAge' is private and only accessible within class 'Person'.

3. 静态类型检查

  • ES6:ES6 的类在运行时进行类型检查,没有编译时的类型检查。
  • TypeScript:TypeScript 在编译时进行类型检查,可以提前发现类型错误,减少运行时错误。

示例

1
2
3
4
5
6
7
8
9
10
11
12
// ES6 类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('Kimi', '25'); // 运行时不会报错,但可能会导致逻辑错误
person.greet(); // Hello, my name is Kimi and I am 25 years old.
1
2
3
4
5
6
7
8
9
10
11
12
13
// TypeScript 类
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): void {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('Kimi', '25'); // 编译时报错:Argument of type 'string' is not assignable to parameter of type 'number'.

4. 构造函数参数属性

  • ES6:ES6 的类不支持构造函数参数属性。
  • TypeScript:TypeScript 支持构造函数参数属性,可以在构造函数参数上使用访问修饰符,自动创建类的属性。

示例

1
2
3
4
5
6
7
8
9
class Person {
constructor(public name: string, private age: number) {
}
greet(): void {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
const person = new Person('Kimi', 25);
person.greet(); // Hello, my name is Kimi and I am 25 years old.

5. 类的继承

  • ES6:ES6 的类支持继承,但没有类型检查。
  • TypeScript:TypeScript 的类支持继承,并且在继承时进行类型检查,确保子类的类型兼容性。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ES6 类的继承
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
makeSound() {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog('Buddy');
dog.makeSound(); // Buddy barks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// TypeScript 类的继承
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
makeSound(): void {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
makeSound(): void {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog('Buddy');
dog.makeSound(); // Buddy barks.

6. 抽象类和接口

  • ES6:ES6 的类不支持抽象类和接口。
  • TypeScript:TypeScript 支持抽象类和接口,可以定义类的结构和方法签名,确保类的实现符合特定的规范。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 抽象类
abstract class Animal {
abstract makeSound(): void;
}
class Dog extends Animal {
makeSound(): void {
console.log('Bark');
}
}
// 接口
interface IAnimal {
makeSound(): void;
}
class Cat implements IAnimal {
makeSound(): void {
console.log('Meow');
}
}

总结

  • ES6:提供了类的基本功能,但没有类型系统和访问修饰符。
  • TypeScript:在 ES6 的基础上添加了类型系统、访问修饰符、构造函数参数属性、抽象类和接口等高级特性,提供了更强大的类型检查和代码组织能力。
    在实际开发中,如果你需要类型检查和更严格的代码规范,推荐使用 TypeScript。如果你的项目不需要类型检查,或者你更倾向于动态类型,可以使用 ES6 的类。
由 Hexo 驱动 & 主题 Keep
访客数 访问量