您好,欢迎访问一九零五行业门户网

怎样使用JS与TypeScript

这次给大家带来怎样使用js与typescript,使用js与typescript的注意事项有哪些,下面就是实战案例,一起来看一下。
前言
对于一个前端开发者来说,很少用到 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('推特治国'); // 特朗普 : 推特治国
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
怎样操作vue2.0 移动端实现下拉刷新和上拉加载
怎样使用vue计算属性与方法侦听器
以上就是怎样使用js与typescript的详细内容。
其它类似信息

推荐信息