怎样对JS+TypeScript中class进行使用
这次给大家带来怎样对JS+TypeScript中class进行使用,对JS+TypeScript中class进行使用的注意事项有哪些,下面就是实战案例,一起来看一下。
前言
对于一个前端开发者来说,很少用到 class ,因为在 JavaScript 中更多的是 函数式 编程,抬手就是一个 function,几乎不见 class 或 new 的踪影。所以 设计模式 也是大多数前端开发者的一个短板。
最近在学习 Angular 的过程中发现其大量的运用了 class,不得不佩服,Angular 确实是一个优秀的、值得深入研究的 框架。
本文将简单的介绍一下 JavaScript 和 TypeScript 中的 class。
基本概念
在介绍 class 之前,要先介绍一些基本的概念。
1、静态成员
类自身的成员,可以继承,但实例无法访问,一般多见于工具类,比如在jQuery时代最常见的 $.ajax ,ajax 便是 $ 的静态方法,使用方便,不需要再通过 new 或者函数调用的得到一个新实例。
2、私有成员
类内部的成员,一般是不能继承的,只能在内部使用,实例无法访问,有一点点像闭包内部的变量,但是还是一定的差别,目前 JavaScript 无法直接定义私有成员,只能通过其它方式辅助实现。
3、getter/setter
存取器属性,当我们访问或者修改一个实例的属性的时候,我们可通过存取器属性拦截这两个操作,从而做一些其它的事情,vue正是通过这个api来实现对数据变化的追踪。
4、实例成员
指 new 出来的实例所具有的成员,可以被继承,也是通过这个特性实现了代码的复用。
5、抽象类,抽象方法
抽象类指不可以被实例化的类,通过 new 关键字调用会报错,一般都被设计成父类。
抽象方法,只提供方法的名称,参数和返回值,不负责实现,具体的实现由子类去完成,如果一个子类继承于抽象类,那么这个子类必须实现父类所有的抽象方法,否则会报错。
这两个概念在 JavaScript 都无法直接实现,但在 TypeScript 或 其它面向对象语言中可以轻松实现,另外这个特性也是用于实现 多态 的重要手段。
案例介绍
为了更好的介绍 class,本文将采用三个 类 来做例子,分别是 Person、Chinese、American。从字面上可以很快的知道: Person 是 父类(基类) ,Chinese 和 American 是 子类(派生类) 。
Person 有 name、age、gender 三个属性,sayHello 方法和 fullName 存取器属性。同时 Person 还有一些 静态成员 和 私有成员 ,由于实在太难想例子了,所以就用 foo、bar、x、y、z 这些来代替吧。
作为子类的 Chinese 和 American 继承了 Person 的实例成员和静态成员。同时它们自身也有一些自己的方法和属性:
Chinese 有 kungfu 属性,会习武 martial。
American 有 twitter,还可以 sendTwitter。
接下来我们就分别使用 JavaScript 和 TypeScript 来实现这个案例。
JavaScript 中的 class
JavaScript 中的 class 要分开说,在 ES6 中提供了两个关键字 class 和 extends ,虽然它们只是语法糖,底层还是再利用 prototype 实现继承的,但是不能否认,这中写法确实让代码更清晰,更易读。
ES6 中的 class
class Person { // #x = '私有属性x'; // static x = '静态属性x'; // name; // age; // gender; // 上面的写法还在提案中,并没有成为正式标准,不过变化的可能性已经不大了。 // 顺便吐槽一下,用 # 表示私有成员,真的是很无语. /** * Person的静态方法,可以被子类继承 * 可以通过 this 访问静态成员 */ static foo() { console.log(`类 ${this.name} 有一个 ${this.x}`); } constructor(name, age, gender) { this.name = name; this.age = age; this.gender = gender; } /** * 数据存储器,可以访问实例成员,子类的实例可以继承 * 以通过 this 访问实例成员 */ get fullName() { const suffix = this.gender === '男' ? '先生' : '女士'; return this.name + suffix; } set fullName(value) { console.log(`你已改名为 ${value} `); } /** * Person的实例方法,可以被子类的实例继承 * 可以通过 this 访问实例成员 */ sayHello() { console.log(`你好我是 ${this.fullName} ,我 ${this.age} 岁了`); } } Person.x = '静态属性x';
class Chinese extends Person { static bar() { console.log(`类 ${this.name} 的父类是 ${super.name}`); super.foo(); } constructor(name, age, gender, kungfu) { super(name, age, gender); this.kungfu = kungfu; } martial() { console.log(`${this.name} 正在修炼 ${this.kungfu} `); } }
class American extends Person { // static y = '静态属性y'; static bar() { console.log(`类 ${this.name} 有自己的 ${this.y} ,还继承了父类 ${super.name} 的 ${super.x}`); } constructor(name, age, gender, twitter) { super(name, age, gender); this.twitter = twitter; } sendTwitter(msg) { console.log(`${this.name} : `); console.log(` ${msg}`); } }
American.y = '静态属性y'; Person.x; // 静态属性x Person.foo(); // 类 Person 有一个 静态属性x Chinese.x; // 静态属性x Chinese.foo(); // 类 Chinese 有一个 静态属性x Chinese.bar(); // 类 Chinese 的父类是 Person American.x; // 静态属性x American.y; // '静态属性y American.foo(); // 类 American 有一个 静态属性x American.bar(); // 类 American 有自己的 静态属性y ,还继承了父类 Person 的 静态属性x const p = new Person('Lucy', 20, '女'); const c = new Chinese('韩梅梅', 18, '女', '咏春拳'); const a = new American('特朗普', 72, '男', 'Donald J. Trump'); c.sayHello(); // 你好我是 韩梅梅女士 ,我 18 岁了 c.martial(); // 韩梅梅 正在修炼 咏春拳 a.sayHello(); // 你好我是 特朗普先生 ,我 72 岁了 a.sendTwitter('推特治国'); // 特朗普 : 推特治国
ES6 之前的 class
ES5 的继承,实质是先创造子类的实例对象 this,
然后再将父类的方法添加到 this 上面 Parent.apply(this) 。
ES6 的继承机制完全不同,实质是先创造父类的实例对象 this,所以必须先调用 super 方法,
然后再用子类的构造函数修改this。
为了实现继承,我们需要先实现一个 extendsClass 函数,它的作用是让子类继承父类的静态成员和实例成员。
function extendsClass(parent, child) { // 防止子类和父类相同名称的成员被父类覆盖 var flag = false; // 继承静态成员 for (var k in parent) { flag = k in child; if (!flag) { child[k] = parent[k]; } } // 继承父类prototype上的成员 // 用一个新的构造函数切断父类和子类之间的数据共享 var F = function () { } F.prototype = parent.prototype; var o = new F(); for (var k in o) { flag = k in child.prototype; if (!flag) { child.prototype[k] = o[k]; } } }
function Person(name, age, gender) { this.name = name; this.age = age; this.gender = this.gender; // 如果将 getter/setter 写在 prototype 会获取不到 Object.defineProperty(this, 'fullName', { get: function () { var suffix = this.gender === '男' ? '先生' : '女士'; return this.name + suffix; }, set: function () { console.log('你已改名为 ' + value + ' '); }, }); } Person.x = '静态属性x'; Person.foo = function () { console.log('类 ' + this.name + ' 有一个 ' + this.x); } Person.prototype = { constructor: Person, // get fullName() { }, // set fullName(value) { }, sayHello: function () { console.log('你好我是 ' + this.fullName + ' ,我 ' + this.age + ' 了'); }, };
function Chinese(name, age, gender, kungfu) { // 用call改变this指向,实现继承父类的实例属性 Person.call(this, name, age, gender); this.kungfu = kungfu; } Chinese.bar = function () { console.log('类 ' + this.name + ' 的父类是 ' + Person.name); Person.foo(); } Chinese.prototype = { constructor: Chinese, martial: function () { console.log(this.name + ' 正在修炼 ' + this.kungfu + ' '); } }; extendsClass(Person, Chinese);
function American(name, age, gender, twitter) { Person.call(this, name, age, gender); this.twitter = twitter; } American.y = '静态属性y'; American.bar = function () { console.log('类 ' + this.name + ' 有自己的 ' + this.y + ' ,还继承了父类 ' + Person.name + ' 的 ' + Person.x); } American.prototype = { constructor: American, sendTwitter: function (msg) { console.log(this.name + ' : '); console.log(' ' + msg); } }; extendsClass(Person, American);
TypeScript 中的 class
讲完了 JavaScript 中的类,还是没有用到 抽象类,抽象方法,私有方法这三个概念,由于 JavaScript 语言的局限性,想要实现这三种概念是很困难的,但是在 TypeScript 可以轻松的实现这一特性。
首先我们稍微修改一下例子中的描述,Person 是抽象类,因为一个正常的人肯定是有国籍的,Person 的 sayHello 方法是抽象方法,因为每个国家打招呼的方式不一样。另外一个人的性别是只能读取,不能修改的,且是确定的是,不是男生就是女生,所以还要借助一下枚举。
enum Gender { female = 0, male = 1 };
abstract class Person { private x: string = '私有属性x,子类和实例都无法访问'; protected y: string = '私有属性y,子类可以访问,实例无法访问'; name: string; public age: number; public readonly gender: Gender; // 用关键字 readonly 表明这是一个只读属性 public static x: string = '静态属性x'; public static foo() { console.log(`类 ${this.name} 有一个 ${this.x}`); } constructor(name: string, age: number, gender: Gender) { this.name = name; this.age = age; this.gender = gender; } get fullName(): string { const suffix = this.gender === 1 ? '先生' : '女士'; return this.name + suffix; } set FullName(value: string) { console.log(`你已改名为 ${value} `); } // 抽象方法,具体实现交由子类完成 abstract sayHello(): void; }
class Chinese extends Person { public kungfu: string; public static bar() { console.log(`类 ${this.name} 的父类是 ${super.name}`); super.foo(); } public constructor(name: string, age: number, gender: Gender, kungfu: string) { super(name, age, gender); this.kungfu = kungfu; } public sayHello(): void { console.log(`你好我是 ${this.fullName} ,我 ${this.age} 岁了`); } public martial() { console.log(`${this.name} 正在修炼 ${this.kungfu} `); } }
class American extends Person { static y = '静态属性y'; public static bar() { console.log(`类 ${this.name} 有自己的 ${this.y} ,还继承了父类 ${super.name} 的 ${super.x}`); } public twitter: string; public constructor(name: string, age: number, gender: Gender, twitter: string) { super(name, age, gender); this.twitter = twitter; } public sayHello(): void { console.log(`Hello, I am ${this.fullName} , I'm ${this.age} years old`); } public sendTwitter(msg: string): void { console.log(`${this.name} : `); console.log(` ${msg}`); } }
Person.x; // 静态属性x Person.foo(); // 类 Person 有一个 静态属性x Chinese.x; // 静态属性x Chinese.foo(); // 类 Chinese 有一个 静态属性x Chinese.bar(); // 类 Chinese 的父类是 Person American.x; // 静态属性x American.y; // '静态属性y American.foo(); // 类 American 有一个 静态属性x American.bar(); // 类 American 有自己的 静态属性y ,还继承了父类 Person 的 静态属性x const c: Chinese = new Chinese('韩梅梅', 18, Gender.female, '咏春拳'); const a: American = new American('特朗普', 72, Gender.male, 'Donald J. Trump'); c.sayHello(); // 你好我是 韩梅梅女士 ,我 18 岁了 c.martial(); // 韩梅梅 正在修炼 咏春拳 a.sayHello(); // Hello, I am 特朗普先生 , I'm 72 years old a.sendTwitter('推特治国'); // 特朗普 : 推特治国
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是怎样对JS+TypeScript中class进行使用的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

类和方法的概念和实例类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。类的构造方法__init__():类有一个名为init()的特殊方法(构造方法),该方法在类实例化时会自动调用。实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self修饰的变量。实例化:创建一个类的实例,类的具体对象。继承:即一个派生类(derivedclass)继承基类(baseclass)的

JavaScript 不提供任何内存管理操作。相反,内存由 JavaScript VM 通过内存回收过程管理,该过程称为垃圾收集。

问题:Vue3+TypeScript+Vite的项目中如何使用require动态引入类似于图片等静态资源!描述:今天在开发项目时(项目框架为Vue3+TypeScript+Vite)需要动态引入静态资源,也就是img标签的src属性值为动态获取,按照以往的做法直接是require引入即可,如下代码:写上后代码波浪线报错,报错提示:找不到名称“require”。是否需要为节点安装类型定义?请尝试使用npmi--save-dev@types/node。ts(2580)在进行了npmi--save-d

如何使用MySQL在TypeScript中实现数据类型转换功能引言:在开发Web应用程序时,数据类型转换是一个非常常见的需求。在处理数据库中存储的数据时,特别是使用MySQL作为后端数据库时,我们经常需要将查询结果中的数据按照我们所需的类型进行转换。本文将介绍如何在TypeScript中利用MySQL实现数据类型转换的功能,并提供代码示例。一、准备工作:在开

class是python中的一个关键字,用来定义一个类,定义类的方法:class后面加一个空格然后加类名;类名规则:首字母大写,如果多个单词用驼峰命名法,如【class Dog()】。

如何使用Redis和TypeScript开发高性能计算功能概述:Redis是一个开源的内存数据结构存储系统,具有高性能和可扩展性的特点。TypeScript是JavaScript的超集,提供了类型系统和更好的开发工具支持。结合Redis和TypeScript,我们可以开发出高效的计算功能来处理大数据集,并充分利用Redis的内存存储和计算能力。本文将介绍如何

jQuery是一种经典的JavaScript库,被广泛应用于网页开发中,它简化了在网页上处理事件、操作DOM元素和执行动画等操作。在使用jQuery时,经常会遇到需要替换元素的class名的情况,本文将介绍一些实用的方法,以及具体的代码示例。1.使用removeClass()和addClass()方法jQuery提供了removeClass()方法用于删除

在编写PHP代码时,使用类(Class)是一个非常常见的做法。通过使用类,我们可以将相关的功能和数据封装在一个单独的单元中,使代码更加清晰、易读和易维护。本文将详细介绍PHPClass的用法,并提供具体的代码示例,帮助读者更好地理解如何在实际项目中应用类来优化代码。1.创建和使用类在PHP中,可以使用关键字class来定义一个类,并在类中定义属性和方法。
