ES6的类 vs TypeScript的类:解密两种语言中的面向对象之争

news2024/9/20 8:07:57

在这里插入图片描述

文章目录

  • ES6 类
    • ES6 类的常见特性
      • 1. 构造函数
      • 2. 实例方法
      • 3. 静态方法
      • 4. 继承
  • TypeScript 类
    • TypeScript 类的特性
      • 1. 类型注解
      • 2. 访问修饰符
      • 3. 类型推断
      • 4. 接口实现

ES6 类

ES6(ECMAScript 2015)引入了类的概念,为 JavaScript 增加了面向对象编程的能力。ES6 中的类是一种语法糖,本质上仍然是基于原型的继承。使用类可以定义构造函数、实例方法和静态方法,并且支持继承和类之间的关系。

ES6 类的常见特性

以下是一些 ES6 类的常见特性:

1. 构造函数

类中的构造函数通过 constructor 关键字定义,并且在创建实例时被调用。

当使用 ES6 类创建对象时,构造函数是在实例化过程中自动调用的方法。构造函数使用 constructor 关键字定义在类内部,它负责初始化对象的属性和状态。

以下是一个使用 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 person1 = new Person('Alice', 28);
person1.greet(); // 输出:Hello, my name is Alice and I am 28 years old.

在上面的例子中,我们创建了一个名为 Person 的类。构造函数 constructor 接受两个参数 nameage,并将它们分别赋值给实例属性 this.namethis.agegreet 方法用于打印出个人信息。

通过使用 new 关键字,我们可以实例化该类并传入相应的参数。在实例化过程中,构造函数会被自动调用,初始化属性。然后,我们可以调用 greet 方法来打印出个人信息。

值得注意的是,ES6 类中的构造函数只能有一个,且使用 super 关键字来调用父类的构造函数(如果有继承关系)。构造函数可以执行各种操作,例如初始化数据、调用其他方法或执行其他逻辑,以确保实例在创建时处于正确的状态。

2. 实例方法

类中的实例方法不需要使用关键字 function 声明,直接在类体内声明即可。实例方法默认会绑定到实例对象。

在 ES6 类中,实例方法是定义在类的原型上的方法,可以被类的实例调用。以下是一个使用 ES6 的实例方法的示例:

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  calculateArea() {
    return Math.PI * this.radius * this.radius;
  }

  calculateCircumference() {
    return 2 * Math.PI * this.radius;
  }
}

const circle1 = new Circle(5);
console.log(circle1.calculateArea()); // 输出:78.53981633974483
console.log(circle1.calculateCircumference()); // 输出:31.41592653589793

在上面的例子中,我们创建了一个名为 Circle 的类。该类有一个构造函数,接受一个参数 radius 并将其赋值给实例属性 this.radius

然后,我们定义了两个实例方法 calculateAreacalculateCircumferencecalculateArea 方法用于计算圆的面积,calculateCircumference 方法用于计算圆的周长。这两个方法都可以通过类的实例进行调用。

使用 new 关键字我们实例化了 Circle 类,并传入半径为 5。然后我们分别调用 calculateAreacalculateCircumference 方法,并打印出结果。

ES6 类中的实例方法是绑定到类的原型上的,这意味着每个类的实例都共享同一个实例方法的实现,从而节省了内存空间。同时,实例方法可以访问类的实例属性和其他实例方法,允许我们在方法内部处理实例的数据和状态。

3. 静态方法

类中的静态方法使用 static 关键字声明,静态方法与实例无关,可以直接通过类来调用。

在 ES6 类中,静态方法是定义在类本身上的方法,而不是类的实例。可以通过类名直接调用静态方法,而不需要创建类的实例。以下是一个使用 ES6 的静态方法的示例:

class MathUtils {
  static add(a, b) {
    return a + b;
  }

  static subtract(a, b) {
    return a - b;
  }
}

console.log(MathUtils.add(5, 3)); // 输出:8
console.log(MathUtils.subtract(10, 4)); // 输出:6

在上面的例子中,我们创建了一个名为 MathUtils 的类。该类定义了两个静态方法 addsubtract。这两个方法都可以直接通过类名进行调用,而不需要创建类的实例。

使用类名 MathUtils 来调用静态方法,并传入相应的参数。然后我们打印出结果。

ES6 类中的静态方法是绑定到类本身的,而不是绑定到类的实例。因此,它们不能访问类的实例属性或其他实例方法。静态方法通常用于执行与类相关的操作,例如辅助函数、工具函数或对象的创建和管理。

可以通过在方法前添加 static 关键字来定义静态方法。静态方法可以通过类名直接调用,而无需实例化对象。这使得静态方法具有更高的灵活性和代码组织性,可以在不创建实例的情况下执行特定的功能。

4. 继承

通过 extends 关键字可以实现类的继承,子类可以继承父类的属性和方法,并可以覆盖或扩展父类的功能。

在 ES6 中,我们可以使用 extends 关键字实现类的继承。通过继承,一个子类可以继承父类的属性和方法,同时可以添加新的属性和方法。以下是一个使用 ES6 实现继承的代码示例:

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a sound.`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  bark() {
    console.log(`${this.name} barks loudly.`);
  }
}

const myDog = new Dog('Max', 'Labrador');
myDog.speak(); // 输出:Max makes a sound.
myDog.bark(); // 输出:Max barks loudly.
console.log(myDog.breed); // 输出:Labrador

在上面的例子中,我们创建了一个名为 Animal 的父类。该类有一个构造函数,接受一个参数 name 并将其赋值给实例属性 this.name。还定义了一个方法 speak,用于输出动物发出声音。

然后,我们创建了一个名为 Dog 的子类,使用 extends 关键字来继承父类 Animal。子类 Dog 有一个构造函数,接受两个参数 namebreed。在子类的构造函数中,我们使用 super 关键字调用父类的构造函数,并传递 name 参数。然后,我们将 breed 参数赋值给子类特有的实例属性 this.breed

子类 Dog 还定义了一个新的方法 bark,用于输出狗的吠声。

通过创建 Dog 类的实例 myDog,我们可以调用继承自父类的方法 speak 和子类自己的方法 bark。还可以访问子类特有的属性 breed

继承允许我们在子类中复用父类的代码和功能,并在子类中添加更多特定的属性和方法。这提高了代码的可重用性和可维护性,并支持面向对象编程的概念,如封装、继承和多态。

TypeScript 类

TypeScript 是一个由 Microsoft 开发的开源编程语言,它是 JavaScript 的一个超集,增加了静态类型检查和面向对象编程的特性。TypeScript 中的类和 ES6 类有相似之处,但又具有更强的类型系统和其他功能。

TypeScript 类的特性

以下是一些 TypeScript 类的特性:

1. 类型注解

TypeScript 强调类型的静态检查,可以在类的属性、方法和参数上添加类型注解,以约束数据类型。

TypeScript 是 JavaScript 的一个超集,它提供了类型注解的功能来静态检查代码。通过类型注解,我们可以为变量、函数参数、函数返回值等添加类型信息,从而使编译器能够检查代码中的类型错误,并在开发过程中提供更好的代码提示和自动补全。

以下是一个使用 TypeScript 的类型注解的代码示例:

function greet(name: string): void {
  console.log(`Hello, ${name}!`);
}

let username: string = "John";
greet(username); // 输出:Hello, John!

在上面的例子中,我们定义了一个名为 greet 的函数。函数接受一个参数 name,并且我们使用 : string 进行类型注解来指定该参数的类型为字符串。

同时,我们还为函数的返回值 void 添加了类型注解,表示该函数没有返回值。

在函数调用时,我们创建一个名为 username 的变量,并将其类型注解为字符串。然后,我们将 username 作为参数传递给 greet 函数。

TypeScript 编译器将根据类型注解进行代码检查,以确保传递给函数的参数类型正确,并且函数的返回值与类型注解一致。

类型注解提供了一种强大的工具,可以增强代码的可读性和可维护性,并提供更好的开发体验。它可以帮助我们在编译阶段发现潜在的类型错误,并减少在运行时出现的错误。此外,类型注解还提供了更好的代码提示和自动补全功能,以提高开发效率。

2. 访问修饰符

TypeScript 提供了 publicprotectedprivate 等访问修饰符,用于控制类成员的访问权限。

TypeScript 提供了访问修饰符来控制类的属性和方法的访问权限。有三种主要的访问修饰符:publicprotectedprivate

下面是一个使用 TypeScript 访问修饰符的示例代码:

class Person {
  public name: string;
  protected age: number;
  private phoneNumber: string;

  constructor(name: string, age: number, phoneNumber: string) {
    this.name = name;
    this.age = age;
    this.phoneNumber = phoneNumber;
  }

  public introduce(): void {
    console.log(`My name is ${this.name}. I am ${this.age} years old.`);
    this.privateMethod();
  }

  protected protectedMethod(): void {
    console.log("This is a protected method.");
  }

  private privateMethod(): void {
    console.log("This is a private method.");
  }
}

class Employee extends Person {
  public position: string;

  constructor(name: string, age: number, phoneNumber: string, position: string) {
    super(name, age, phoneNumber);
    this.position = position;
  }

  public getPhoneNumber(): void {
    console.log(`${this.name}'s phone number is ${this.phoneNumber}.`);
    this.protectedMethod();
  }
}

const john = new Person("John", 30, "123456789");
console.log(john.name); // 公有属性,可以访问
// console.log(john.age); // 受保护属性,不能在类外部访问
// console.log(john.phoneNumber); // 私有属性,不能在类外部访问
john.introduce(); // 公有方法,可以访问

const employee = new Employee("Bob", 25, "987654321", "Manager");
// console.log(employee.name); // 公有属性,可以访问
// console.log(employee.age); // 受保护属性,不能在类外部访问
// console.log(employee.phoneNumber); // 私有属性,不能在类外部访问
employee.introduce(); // 公有方法,可以访问
employee.getPhoneNumber(); // 子类可以访问受保护方法

在上面的示例中,我们创建了一个名为 Person 的基类,并定义了三个属性:nameagephoneNumbername 是公有属性,可以在类外部访问;age 是受保护属性,只能在类内部及其子类中访问;phoneNumber 是私有属性,只能在类内部访问。

我们还定义了两个方法:introduceprotectedMethodprivateMethodintroduce 是公有方法,可以在类外部调用;protectedMethod 是受保护方法,只能在类内部及其子类中调用;privateMethod 是私有方法,只能在类内部调用。

然后,我们创建了一个名为 Employee 的子类,继承自 Person。子类拥有 position 属性,并在构造函数中通过 super 关键字调用父类的构造函数来初始化继承的属性。

通过创建 PersonEmployee 的实例,我们可以看到不同访问修饰符的效果。只有公有属性和方法可以从类外部访问,受保护属性和方法只能在类内部及其子类中访问,而私有属性和方法只能在类内部访问。

访问修饰符允许我们控制类的成员的可见性和可访问性,并提供了一种封装数据和行为的方式,增强了代码的安全性和可维护性。

3. 类型推断

TypeScript 可以根据赋值表达式的右侧推断出变量的类型,减少重复的类型注解。

TypeScript 提供了类型推断的功能,能够根据赋值表达式的右侧值自动推断变量的类型。下面是一个使用 TypeScript 类型推断的示例代码:

let name = "Alice"; // 类型推断为 string
let age = 30; // 类型推断为 number
let isStudent = true; // 类型推断为 boolean

let fruits = ["apple", "banana", "orange"]; // 类型推断为 string[]
let numbers = [1, 2, 3]; // 类型推断为 number[]
let matrix = [[1, 2], [3, 4]]; // 类型推断为 number[][]

let person = {
  name: "Bob",
  age: 25,
}; // 类型推断为 { name: string, age: number }

function add(a: number, b: number) {
  return a + b;
} // 函数参数和返回值的类型推断为 number

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
} // 类的属性和构造函数参数的类型推断为 string

let animal = new Animal("Dog"); // 类的实例类型推断为 Animal

在上述示例中,我们声明了一些变量并初始化它们,TypeScript 根据赋值的值来推断变量的类型。例如,通过字符串赋值给变量 name,TypeScript 推断出 name 的类型为 string

类似地,数组的元素类型也可以通过初始化的值进行推断。在示例中,fruits 的类型被推断为 string[],即字符串数组。

在函数定义中,参数 ab 的类型被推断为 number,因为我们在函数体内使用了加法操作,而返回值的类型也被推断为 number

对于类,属性和构造函数参数的类型也可以通过初始化来推断。在示例中,Animal 类的属性 name 和构造函数参数 name 都被推断为 string 类型。

最后,当我们创建 Animal 类的实例 animal 时,TypeScript 推断出它的类型为 Animal

类型推断是 TypeScript 的一个强大功能,能够减少显式类型注解的冗余,并帮助开发人员更轻松地编写类型安全的代码。

4. 接口实现

TypeScript 支持类实现接口,通过 implements 关键字来强制类遵循接口的契约。

在 TypeScript 中,接口(Interfaces)用于定义对象的结构和类型。一个类可以通过实现(implements)一个接口来强制遵循该接口所定义的结构。下面是一个使用 TypeScript 接口实现的示例代码:

interface Shape {
  getArea(): number;
}

class Circle implements Shape {
  radius: number;

  constructor(radius: number) {
    this.radius = radius;
  }

  getArea(): number {
    return Math.PI * this.radius ** 2;
  }
}

class Rectangle implements Shape {
  width: number;
  height: number;

  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }

  getArea(): number {
    return this.width * this.height;
  }
}

const circle = new Circle(5);
console.log(circle.getArea()); // 输出: 78.53981633974483

const rectangle = new Rectangle(4, 6);
console.log(rectangle.getArea()); // 输出: 24

在上述示例中,我们定义了一个名为 Shape 的接口,它有一个名为 getArea 的方法,返回类型为 number

然后我们创建了两个类 CircleRectangle,它们分别实现了 Shape 接口。这意味着这两个类必须实现 Shape 接口中定义的方法 getArea

Circle 类有一个属性 radius,并在构造函数中初始化。它实现了 getArea 方法来计算圆的面积。

Rectangle 类有两个属性 widthheight,并在构造函数中初始化。它同样实现了 getArea 方法来计算矩形的面积。

通过创建 CircleRectangle 类的实例,并调用它们的 getArea 方法,我们可以得到圆和矩形的面积。

接口的使用使得我们能够在 TypeScript 中定义和强制对象的结构,并确保类遵循指定的接口约束。这提高了代码的可读性和可维护性,并加强了类型检查和类型安全性。

总结来说,ES6 类是 JavaScript 中基于原型的面向对象编程的语法糖,而 TypeScript 类在此基础上增加了强类型检查和其他面向对象编程的特性,使得代码更具可读性、可维护性和可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/709229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

费马原理与光的反射折射

费马原理:光传播的路径是光程取极值的路径 光的反射 如上图所示,光从P点出发射向x点,反射到Q点。 P 点到 x 点的距离 d 1 x 2 a 2 d1 \sqrt{x^2 a^2} d1x2a2 ​ Q 点到 x 点的距离 d 2 b 2 ( l − x ) 2 d2 \sqrt{b^2 (l-x)^2} d2…

WebAPIs-DOM操作元素属性/自定义属性

Web APIs web APIs 操作页面元素做出各种效果 DOM 文档对象模型 使用js操作页面文档 BOM 浏览器对象模型 使用js操作浏览器 API 应用程序接口 接口:无需关心内部如何实现,只需要调用就可以很方便实现某些功能 作用:使用js提供的接口来操…

SQL事务与隔离

事务 事务的定义 事务是完成一个任务的多条语句,这些语句中,只要有一条语句失败,那么整个事务就会失败,即使之前的语句已经执行完毕也会被撤回 举个例子: 我去银行给王哥转钱,这个转钱呢分两个步骤,第一步先把我的钱拿出来,第二步把钱给王哥,那万一刚把我钱拿出来但是没到王…

大数据分析案例-基于LightGBM算法构建公司破产预测模型

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

1.网络基础

什么是网络? 信息传递,资源共享 计算机—1946年2月14日—电脑 电流—二进制— 1001—人类语言(抽象语言)—应用程序—编译—编码—应用层 把人类语言转化为二进制—表示层(编码表) 网路层——路由器&#x…

AI 绘画 - 建筑绘图辅助设计之生图

前情提要 2023-06-16 周五 杭州 小雨 小记: 今天下班,回来比较晚,端午节去看老弟,只希望下周不要那么多乱七八糟的事情了,继续AI 绘画,之前上学的时候从来不爱做笔记的,现在或许是老了吧,。 …

C语言复习笔记5

1.函数 #include<stdio.h>void Add(int *p) {(*p); }int main() {int time0;Add(&time);printf("%d\n",time);return 0; }2.二分查找 #include<stdio.h>void Add(int *p) {(*p); }int main() {int time0;Add(&time);printf("%d\n",t…

Linux常用命令——findfs命令

在线Linux命令查询工具 findfs 标签或UUID查找文件系统 补充说明 findfs命令依据卷标&#xff08;Label&#xff09;和UUID查找文件系统所对应的设备文件。findfs命令会搜索整个磁盘&#xff0c;看是否有匹配的标签或者UUID没有&#xff0c;如果有则打印到标注输出上。find…

Spring中的设计模式

目录 1.Spring中使用到的设计模式有&#xff1a; 2.工厂模式 3.单例模式 4.代理模式 5.模板模式 6.适配器模式 1.Spring中使用到的设计模式有&#xff1a; 工厂模式&#xff1a;实现IoC容器 单例模式&#xff1a;将bean设置为单例 代理模式&#xff1a;AOP的底层实现 模板…

聊一聊.NET的网页抓取和编码转换

在本文中&#xff0c;你会了解到两种用于 HTML 解析的类库。另外&#xff0c;我们将讨论关于网页抓取&#xff0c;编码转换和压缩处理的知识&#xff0c;以及如何在 .NET 中实现它们&#xff0c;最后进行优化和改进。 文章目录 1. 背景2. 网页抓取3. 编码转换4. 网页压缩处理5.…

C#,数值计算——哈夫曼编码与数据压缩技术(Huffman Coding and Compression of Data)源代码

1 霍夫曼编码导论 霍夫曼编码是一种基于数据集中符号频率的无损数据压缩形式。它是一种前缀编码方案&#xff0c;这意味着编码的数据不包含任何冗余比特。霍夫曼编码广泛应用于各种应用&#xff0c;如图像和视频压缩、数据传输和数据存储。 2 霍夫曼编码的优点 以下是霍夫曼编…

[LeetCode周赛复盘] 第 326 场周赛20230702

[LeetCode周赛复盘] 第 326 场周赛20230702 一、本周周赛总结6909. 最长奇偶子数组1. 题目描述2. 思路分析3. 代码实现 6916. 和等于目标值的质数对1. 题目描述2. 思路分析3. 代码实现 6911. 不间断子数组1. 题目描述2. 思路分析3. 代码实现 6894. 所有子数组中不平衡数字之和…

【小沐学Unity3d】Unity播放视频(VideoPlayer组件)

文章目录 1、简介2、脚本播放示例3、界面播放示例3.1 2d界面全屏播放3.2 2d界面部分区域播放3.3 3d模型表面播放 结语 1、简介 使用视频播放器组件可将视频文件附加到游戏对象&#xff0c;然后在运行时在游戏对象的纹理上播放。 视频播放器 (Video Player) 组件: 属性功能Sourc…

Java实现OpenAI 模型训练(fine-tune)

本文章介绍如何用java实现OpenAI模型训练&#xff0c;仅供参考 提前准备工作 OpenAI KEY&#xff0c;获取方式可自行百度需要自备VPN 或 使用国外服务器转发需要训练的数据集&#xff0c;文章格式要求为JSONL&#xff0c;格式内容详见下图&#xff08;尽量不要低于500个问答&…

openai

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;人工智能。 目录 1、简介2、如何实现3、api文档 1、简介 OpenAI 提供了一个名为 OpenAI API 的库&#xff0c;用…

npm构建vite项目

基础环境 npm init vitelatest 依次输入项目名称、使用框架、使用语言。 生成的项目 进入目录&#xff0c;安装依赖&#xff0c;启动项目。 cd 0702_demo01npm installnpm run dev

网络安全进阶学习第四课——SSRF服务器请求伪造

文章目录 一、什么是SSRF&#xff1f;二、SSRF成因三、SSRF简析四、PHP存在SSRF的风险函数五、后台源码获取方式六、SSRF危害七、SSRF漏洞挖掘从WEB功能上寻找&#xff0c;从URL关键字中寻找 八、SSRF具体利用ssrf常利用的相关协议PHP伪协议读取文件端口扫描 九、SSRF存在的必要…

架构分层方法指导

在《不过时的经典层架构》里讲了经典的四层架构怎样对易变性做封装。咱们实际项目中&#xff0c;如果没有足够的实践和关键性思考&#xff0c;还是很可能使用名义上科学的分类理论&#xff0c;却在按照功能进行架构分层。今天咱们就通过一些简单的指导来尽量减少这种风险。 四问…

LeetCode 75 —— 70. 爬楼梯

LeetCode 75 —— 70. 爬楼梯 一、题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法…

机器学习笔记 - 基于OpenCV和Vantage-point tree构建图像哈希搜索引擎

一、关于图像哈希 上一篇文章中,了解到了图像哈希是使用算法为图像分配唯一哈希值的过程。在深度学习普及之前,一些搜索引擎使用散列技术来索引图像。 言外之意目前的图像搜索引擎主要都是基于深度学习的技术,不过思路都是一样的,我们这里基于OpenCV提供的图像哈希技术构建…