中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript和TypeScript中class的示例分析

發布時間:2021-09-03 11:54:53 來源:億速云 閱讀:149 作者:小新 欄目:web開發

這篇文章主要介紹了JavaScript和TypeScript中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('推特治國'); // 特朗普 : 推特治國

感謝你能夠認真閱讀完這篇文章,希望小編分享的“JavaScript和TypeScript中class的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

唐河县| 鞍山市| 图们市| 铜川市| 井陉县| 尉犁县| 临安市| 满城县| 射洪县| 大丰市| 寿宁县| 廉江市| 通道| 青神县| 集安市| 通州区| 柳江县| 洪泽县| 会东县| 三河市| 石门县| 庄河市| 杭锦后旗| 兴化市| 岱山县| 三明市| 汪清县| 武清区| 惠水县| 青州市| 达拉特旗| 榆中县| 三门峡市| 永丰县| 巴楚县| 吉首市| 黄骅市| 札达县| 尚志市| 罗山县| 乌鲁木齐市|