1. 程式人生 > 其它 >前端開發系列042-基礎篇之TypeScript語言特性(二)

前端開發系列042-基礎篇之TypeScript語言特性(二)

title: '前端開發系列042-基礎篇之TypeScript語言特性(二)'
tags:
  - javaScript系列
  - TypeScript系列

categories: []
date: 2017-11-20 18:05:13

這篇文章中我們將繼續在語言特性方面展開探討,主要介紹了TypeScript中流程控制結構、類以及介面等方面的內容,需要說明的是這篇文章中並不會就相關特性的細節深入展開,你能得到的將只有對它們進行的淺嘗輒止介紹。

一、流程控制結構

我們知道世界上所有的程式都可以簡單劃分為順序、分支和迴圈這三種結構,使用這三種基本結構組合能夠表示所有複雜的結構。順序結構就是按固定的順序來執行特定的程式碼(通常是自上而下執行),分支結構

根據條件判斷結果來確定執行那條路徑,而迴圈結構用於處理需要重複執行的任務,通常迴圈結構由初始條件、迴圈檢測條件、迴圈體以及退出機制組成。TypeScript語言中的流程控制結構和JavaScript保持一致。

迴圈結構

TypeScript語言中的迴圈結構主要有:while迴圈do..while迴圈for..in迴圈以及常用*for迴圈,下面分別介紹並給出示例程式碼。

//檔案路徑 ../02-流程控制結構/01-迴圈結構.ts

//[001] while迴圈結構
//說明:while語句用來在滿足判斷條件的情況下重複執行一段程式碼,程式碼在執行的時候會先檢查判斷條件是否滿足,
//如果條件滿足則執行迴圈體(更新條件變數),否則就結束當前迴圈執行後面的程式碼,重複這個過程
let i:number = 0;
while(i < 5)
{
  i++;
  console.log(i);
}

//[002] do..while迴圈結構
//說明:do...while迴圈結構能夠保證迴圈體至少會被執行一次,當迴圈體執行完後,程式碼會檢查判斷條件是否滿足,
//如果滿足條件則繼續執行迴圈體,否則就結束當前迴圈執行後面的程式碼,重複這個過程
let j:number = 5;
do{
  j--;
  console.log(j);
}while(j>0);


//[003] for迴圈
//說明:執行for迴圈的時候的執行順序為
//(1) 執行初始化語句,初始化變數n
//(2) 檢查是否滿足迴圈條件
//    A: 如果滿足迴圈條件,那麼就執行迴圈體,並跳轉到(3)
//    B: 如果不滿足迴圈條件,那麼就結束當前迴圈,繼續執行後面的任務
//(3) 更新迴圈變數,這裡為n++操作
//(4) 跳轉到(2)

//關於break、continue和return
//在迴圈體中,如果遇到break和return則表示結束迴圈(迴圈本身以及迴圈內後面的程式碼不再執行),執行迴圈後面的任務
//如果遇到continue則表示結束當前迴圈,繼續執行後面的迴圈任務
for(let n:number = 0 ; n < 5; n++)
{
    if(n === 3) continue;
    console.log(n);
}

//[004] for..in迴圈
//說明:for..in迴圈主要用於遍歷程式碼中的物件
//注意:不推薦使用for..in迴圈來遍歷陣列或偽陣列物件,因為它會把原型成員迭代出來。
let obj:any = {name:"zs",age:18,"des":"描述資訊"};
for( let key in obj)
{
  console.log("當前迴圈的key: "+key+" value:"+obj[key]);
}

分支結構

TypeScript語言中的分鐘結構主要有if..else語句switch語句,同JavaScript語言保持一致。下面還是貼出簡短的程式碼示例:

//檔案目錄 ../02-流程控制結構/02-分支結構.ts

//分支結構其實就是林中路在某個節點分叉為多條,而只能選擇其中一條路繼續走下去
//具體走哪條路就像是人生抉擇,得出結選擇論的部分被稱為判斷條件,是布林型別的值(true/fasle)

//[01] if條件語句結構
//當條件滿足的時候,執行{}中的程式碼,否則就忽略
let temp:boolean = true;
if(temp)
{
  console.log("temp的值為true")
}
//.....

//[02] if...else語句結構
//給定兩條路,只能也必須走某一條
if(temp)
{
  console.log("temp的值為true")
}else{
  console.log("temp的值為false")
}


//[03] if...else if...語句結構
//給定多條路,根據條件進行選擇其中的一條
let i:number = 85;
if(i >= 90)
{
  console.log("優秀")
}else if(i >= 80){
  console.log("良好")
}else if(i >= 60)
{
  console.log("及格")
}else
{
  console.log("不及格")
}

//輸出結果為:良好

//[04] switch結構
//switch語句接受一個表示式,會將表示式的值和case語句進行匹配,然後執行關聯的語句塊。
//為提高程式碼的可讀性,避免魔法數字等出現,常結合列舉型別組織程式碼結構
enum Animal{
  Dog,
  Cat,
  Pig
}
let animalType:any = Animal.Dog;
switch(animalType)
{
  case Animal.Dog:
    console.log("Dog: 汪汪汪!!!");
    break;
  case Animal.Cat:
      console.log("Cat: 喵喵喵!!!");
      break;
  case Animal.Pig:
      console.log("Pig: 呵呵呵!!!");
      break;
  default:
      console.log("其他動物...");
}

二、 類(Class)

我們知道JavaScript本身支援面向物件程式設計,但實現的方式和其它典型面向物件程式語言截然不同,JavaScript中沒有Class的概念,其多型、繼承等特性主要依靠函式和原型機制來實現,這種實現機制讓很多java/C++型開發者困惑不已。

從ES6開始,JavaScript將支援基於類的面向物件實現。 在TypeScript中,允許開發者現在就使用Class特性,並且編譯後的JavaScript可以在所有主流瀏覽器和平臺上執行,而不需要等到下個JavaScript版本。

下面給出TypeScript中類的典型結構:

//檔案路徑 ../03-Class的使用/01-Class的典型結構.ts

//類的定義
class Person{
  age:number;       //age屬性
  name:string;      //name屬性
  constructor(name:string,age:number){    //呼叫時內部自動執行該程式碼段
    this.age = age;
    this.name = name;
    console.log("執行內部的建構函式.");
  }
  getInfo(){      //getInfo方法
    return "姓名:" + this.name + " 年齡:" + this.age
  }
}

//使用new來構造Greeter類的例項物件
var p = new Person("wendingding",18);
console.log(p);

上面的程式碼中,我們定義了一個名為Person的類,這個類擁有四個成員為:name屬性、 age屬性、getInfo方法和constructor建構函式。在Class的內部,我們可以通過 this來引用類中的成員。

當類被定義之後,我們可以使用 new來呼叫這個Class。 具體執行的時候,它會先呼叫Class中定義的建構函式執行初始化操作,並創建出一個當前類的例項物件返回。

下面貼出上面程式碼編譯為JavaScript程式碼後的結構:

var Person = /** @class */ (function () {
    function Person(name, age) {
        this.age = age;
        this.name = name;
        console.log("執行內部的建構函式.");
    }
    Person.prototype.getInfo = function () {
        return "姓名:" + this.name + " 年齡:" + this.age;
    };
    return Person;
}());
//使用new來構造Greeter類的例項物件
var p = new Person("wendingding", 18);
console.log(p);

通過觀察可以發現,類其本質上是依靠閉包函式和原型物件來實現的

當我們在TypeScript語言中定義類的時候,該類中所有的屬性和方法預設都是公開的。對於Class的其它細節,這裡我們不做展開。

三、介面(interface)

TypeScript提供了介面機制。其實,TypeScript其核心原則之一就是能夠對值所具有的結構進行型別檢查,這種處理方式被稱為“鴨式辨型法”。我們可以利用介面來為程式碼定義契約。

如果在設計某個函式的時候,我們希望該函式接受的引數物件(即函式的引數是一個物件)必須包含某個指定的屬性,且型別固定。假設函式名為logNameAndOtherInfo,傳遞給該函式的物件引數必須要擁有name這個屬性,且型別必須為string,我們可以嘗試給出如下程式碼

function logNameAndOtherInfo(obj:any){
  console.log("name:"+obj.name);
  console.log("Other:預設的其它資訊,這裡不做處理");
}

let obj1:any = {name:"文頂頂",age:18};
let obj2:any = {color:"red",age:18};
logNameAndOtherInfo(obj1);  //name:文頂頂 //Other:預設的其它資訊,這裡不做處理
logNameAndOtherInfo(obj2);  //undefined   //Other:預設的其它資訊,這裡不做處理

觀察上面的程式碼,我們會發現logNameAndOtherInfo函式無力在展示函式引數物件內部屬性和型別方面有所作為。這種場景下,介面就可以派上用場。

//檔案路徑 ../03-Class的使用/03-介面簡單示例02.ts

interface ObjWithNameValue {
  name: string;
}

function logNameAndOtherInfo(obj:ObjWithNameValue){
  console.log("name:" + obj.name);
  console.log("Other:預設的其它資訊,這裡不做處理");
}

let obj1:any = {name:234,age:18};
let obj2:any = {color:"red",age:18};
logNameAndOtherInfo(obj1);  //name:文頂頂 //Other:預設的其它資訊,這裡不做處理
logNameAndOtherInfo(obj2);  //undefined   //Other:預設的其它資訊,這裡不做處理

除此之外,TypeScript中的介面與C#或Java裡的基本作用一樣,也能夠用它來明確的強制一個類去符合某種契約。

//檔案路徑 ../03-Class的使用/03-介面簡單示例03.ts

interface PersonInterface {
    name: string;
    getInfo();
}

//類的定義,需要遵循介面的約定
class Person implements PersonInterface{
  //報錯:Property 'name' in type 'Person' is not assignable to the same property in base type 'PersonInterface'.
  //name:number;      錯誤的演示(型別和介面不一致)
  name:string;
  constructor(name:string){    //呼叫時內部自動執行該程式碼段
    this.name = name;
    console.log("執行內部的建構函式.");
  }
  getInfo(){      //getInfo方法
    return "姓名:" + this.name;
  }
}

//使用new來構造Greeter類的例項物件
var p = new Person("wendingding.com");

程式碼說明:在上面的程式碼中,我們定義了一個名為PersonInterface的介面,和一個實現了該介面的Person類,它能夠確保實現了介面的類一定擁有指定的結構。

型別檢查器不會去檢查屬性的順序,只要相應的屬性存在並且型別匹配即可。

備註:該文章所有的示例程式碼均可以點選在Github託管倉庫獲取