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

这篇具有很好参考价值的文章主要介绍了ES6的类 vs TypeScript的类:解密两种语言中的面向对象之争。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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 类在此基础上增加了强类型检查和其他面向对象编程的特性,使得代码更具可读性、可维护性和可靠性。文章来源地址https://www.toymoban.com/news/detail-514886.html

到了这里,关于ES6的类 vs TypeScript的类:解密两种语言中的面向对象之争的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • typeScript中的类以及类的限制

    传统方法中,JavaScript通过构造函数实现类的概念,通过原型链实现继承。而在Es6中,我们终于迎来了class. typeScript除了实现了所有Es6中类的功能以外,还添加了一些新的用法。 虽然 JavaScript 中有类的概念,但是可能大多数 JavaScript 程序员并不是非常熟悉类,这里对类相关的概

    2024年02月05日
    浏览(37)
  • ES6基础知识五:你是怎么理解ES6新增Set、Map两种数据结构的?

    如果要用一句来描述,我们可以说 Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构 什么是集合?什么又是字典? 集合 是由一堆无序的、相关联的,且不重复的内存结构【数学中称为元素】组成的组合 字典 是一些元素的集合。每个元素有一个称作key 的域,不同

    2024年02月16日
    浏览(37)
  • ES6中新增的Set/Map两种数据结构

    Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构🧀🧀🧀 什么是集合?什么又是字典? 集合 是由一堆无序的、相关联的、且不重复的内存结构【数学中称之为元素】组成的组合 字典 是一些元素的集合。每个元素有一个称作key的域,不同元素的key各不相同 区别

    2024年02月07日
    浏览(39)
  • JS 怎么理解ES6新增Set、Map两种数据结构?

    目录 一、前言 二、Set 1.Set数据结构定义 2.Set数据结构的特性 3.Set数据结构的基本使用 4.Set遍历数据 5.Set 的使用场景 6.WeakSet的使用 7.垃圾回收机制 三、Map 1.Map数据结构定义 2.Map数据结构的特性 3.Map数据结构的基本使用  4.Map遍历数据 5.Map的使用场景 6.WeakMap的使用 7.垃圾回收

    2024年02月08日
    浏览(37)
  • 【es6】中的Generator

    Generator 函数是 ES6 提供的一种异步编程解决方案,最大特点交出函数的执行权。 和普通函数不一样的是必须调用next()才会执行函数。 function与函数名之间有个(*)号; 不同于普通函数,可暂停执行,所以加 * 区别。 Generator 函数体内部使用yield语句,可以定义不同的内部状态

    2024年02月12日
    浏览(34)
  • ES6中的数值扩展

    二进制和八进制的前缀分别为0b(或0B)和0o(或0O)表示 在ES5的严格模式下,八进制不再允许使用前缀 0 表示 如果要将 0b 和 0x 前缀的字符串数值转为十进制,要使用Number方法 Number.isFinite() 用来检测一个数值是否是有限的(finite)。 Number.isNaN() 用来检测一个值是否为NaN 这两个方法与

    2024年02月07日
    浏览(44)
  • 【ES6】JavaScript中的Symbol

    Symbol是JavaScript中的一种特殊的、不可变的、不可枚举的数据类型。它通常用于表示一个唯一的标识符,可以作为对象的属性键,确保对象的属性键的唯一性和不可变性。 Symbol.for()是Symbol的一个方法,它用于创建一个已经注册的Symbol对象。当使用Symbol.for()创建Symbol对象时,会

    2024年02月10日
    浏览(45)
  • 【ES6】解构语句中的冒号(:)

    在解构赋值语法中,冒号(:)的作用是为提取的字段指定一个新的变量名。 让我们以示例 const { billCode: code, version } = route.query 来说明: { billCode: code, version } 表示从 route.query 对象中提取 billCode 和 version 字段。 冒号(:)后面的 code 是新的变量名,表示将 billCode 字段的值赋给

    2024年01月21日
    浏览(41)
  • ES6+--》熟知JS中的async函数

    目录 async函数 await 表达式 async使用形式 async读取文件 async发送AJAX请求 与生成器(Generator)相比 async函数的返回值为 promise 对象,promise对象的结果由async函数执行的返回值决定。async函数能使得异步操作变得更加方便,简而言之就是 Generator 的语法糖。 定义async函数,特点是即便

    2024年01月17日
    浏览(43)
  • 【ES6】 JavaScript 中的Object.assign

    Object.assign() 是 JavaScript 中的一个方法,它用于复制源对象的所有可枚举属性到目标对象。该方法会返回目标对象。 这是其基本用法: 在这个例子中,source 对象的所有可枚举属性都被复制到了 target 对象。 需要注意的是,Object.assign() 是浅复制(shallow copy),意味着如果源对

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包