Learining TypeScript (一) TypeScript 簡介 node
1. 設計目標 2 typescript
一、類型 7 數組
二、變量、基本類型和運算符 8 瀏覽器
三、流程控制語句 12 服務器
四、函數 12 架構
1、TypeScript出現的背景
在過去的幾年裏,基於JavaScript的Web應用的數量呈幾何級數增加,雖然目前ES6(即ECMAScript2015,從ES6開始採用年份命名)的標準在2015年6月份已經發布了,增添了許多新的特性,例如:模塊和類,以及一些實用的特性,例如Map,Sets,Generates,Promises等等,支持向後兼容,全部的老代碼也能夠正常運行,但目前爲止尚未一個徹底支持ES6標準的JavaScript代理,不管是瀏覽器仍是服務器環境,因此開發者不得不將ES6代碼向ES5轉義,因此ES6標準的普遍應用,還須要一個漫長的過程。
爲了解決JavaScript的維護和擴展問題,微軟花了兩年的時間開發出TypeScript,並在2012年10月公佈了第一個公開的版本。它是JavaScript的一個超集,它與現存的JavaScript代碼有很是高的兼容性,任何合法的JavaScript程序都是合法的TypeScript程序,另外它還給大型項目提供一個構建機制,TypeScript(如下簡稱ts)中加入了基於類(Class)的對象、接口和模塊,採用面向對象編程的方式。至此ts就誕生了。
2、TypeScript的架構
學習的過程就是這樣,當你學習一門新的東西的時候,老是要從基礎知識開始學起,這樣有利於你之後的學習,還有個做用是,給你之後的面試提供很大的幫助。
一、設計目標
咱們能夠從如下幾點中瞭解到,決定TypeScript做爲程序語言發展到今天這個形態的設計目標和架構:
ts在編譯時默認使用ES3標準進行編譯,極大的提升了瀏覽器的兼容性,固然它也支持ES5和ES6的標準。通常狀況下使用任意受支持的編譯目標,咱們均可以使用ts特性,但部分特性須要ES5或更高的版本版本做爲編譯目標的先決條件。
二、TypeScript組件
TypeScript語言內部主要被分爲三層,每一層又被依次分爲子層或者組件,以下圖所示:
每一層都有不一樣的用途:
3、TypeScript語言特性
在介紹TypeScript語言特性以前,首要任務是要搭建開發環境,官方提供了一個在線編輯器http://www.typescriptlang.org/play/ 該編輯器以下圖所示:
編輯器左側編寫TypeScript代碼,右側會自動編譯成JavaScript代碼,固然做爲咱們專業的programmer來講,不多會採用這種在線編輯的方式進行開發了,能夠下載安裝TypeScript的編譯器,做爲一個.Net Developer來講,咱們能夠時候用Visual Studio,從VS2015開始,自動集成了TypeScript的開發環境,若是是如下版本,須要去官方下載TypeScript插件,固然咱們如今推薦你使用VS2017了。除了這些以外,若是想在其餘操做系統中開發,OSX和Linux,那咱們能夠選擇一些比較流行的編輯器,他們都會有TypeScript插件,好比Visual Studio Code(如下成爲VS Code),Sublime等,這裏我推薦VS Code,它較Visual Studio不一樣在於前者是IDE集成開發環境,然後者定義爲Eidtor(編輯器),咱們不須要去安裝Visual Studio幾十個G的安裝包,並且VS Code已經提供了成千上萬的插件供你使用,你本身也能夠去開發本身的插件,如圖所示:
微軟大大一直以來都是那麼的貼心。VS Code提供了各操做系統的版本,能夠直接下載使用。
選擇好咱們的開發編輯器後,就要安裝TypeScript,須要用到npm命令,可是在使用npm命令前,須要在開發環境中安裝node.js,地址https://nodejs.org,找到對應的版本下載便可。驗證是否安裝成功,可以使用
npm –version 查看npm版本
下面咱們可使用命令安裝TypeScript了
npm install -g typescript
(-g)爲全局安裝,可是若是你是OS X用戶,須要使用sudo命令,須要獲取管理員權限,
sudo npm install -g typescript
可使用 tsc -v 命令驗證是否安裝成功
Ok,至此咱們的開發環境就搭建完成了。
如今咱們建立一個test.ts文件,保存一個文件夾內,裏面輸入如下代碼:
var t : number = 1;
而後切換到此文件夾內,執行
tsc test.ts
此時能夠發現,在同目錄下,會編譯生成一個test.js文件。如圖:
一、類型
咱們已經知道,ts是js的超集,ts經過向js增長可選的靜態類型聲明來把js變成強類型語言,可選的靜態類型聲明可約束函數,變量,屬性等程序實體,這樣編譯器和相應的開發工具就能夠在開發過程當中提供更好的正確性驗證和輔助功能(好比IntellSense)。還可讓程序員對本身的和其餘開發人員的代碼表達他的意圖,另外ts的類型檢測在編譯器運行而且沒有運行時開銷。
好比:
var counter; //未知(any)類型
var counter=0; //number類型(推斷出的)
var counter:number; // number類型
var counter:number=0; // number類型
二、變量、基本類型和運算符
這部分簡要說明,對ts的基本類型包括boolean、number、string、array、void和全部用戶自定義的enum類型。全部的這些類型都是any類型的子類型。來看幾種特殊的類型的用法:
第一種:
var list:number[]=[1,2,3];
第二種是使用範型數組類型Array:
var list:Array<number>=[1,2,3];
enum Color{Red,Green,Blue};
var c:Color=Color.Red;
function warnUser:void{
alert("This is my warning message!");
}
var TestStr; //變量聲明但未初始化
alert(TestStr); //顯示undefined
alert(typeof TestStr); //顯示undefined
var TestStr=null; //變量聲明,而且被賦值爲null
alert(TestStr); //顯示null
alert(typeof TestStr); //顯示object
然而在TypeScript中,null和undefined不能看成類型來使用:
var TestStr:null; //錯誤,類型錯誤
var TestStr:undefined; //錯誤,找不到undefined
在TypeScript中,當聲明一個變量時,可使用var 、let和const關鍵字:
var myNum:number=-1;
let isValid:Boolean=true;
const appid:string="0FDFD-8989-4CC3-9080-CSDJJFID7HJFD9";
var 聲明的變量保存在最近的函數做用域中,若是不存在任何函數中則在全局做用域中。
let聲明的變量保存在最近的比函數做用域小的塊做用域中,若是不存在則在全局做用域中。
const關鍵字會建立一個保存在建立位置做用域中的常量,能夠是全局做用域也能夠是塊做用域,這代表const是塊做用的,關於做用域的知識會在後面進一步瞭解。
TypeScript容許聯合聲明:
var path:string[]|sring;
path='/temp/log.xml';
path=['/temp/log.xml', '/temp/info.xml'];
path=1;
此時path=1;會報類型錯誤,由於在聲明時並未對path進行number的合法聲明。
能夠在運行時使用typeof或者instanceof運算符對類型進行驗證。TypeScript語言服務會在if區域尋找這些運算符,而後對應地更改類型:
var x: any = { /* ... */ };
if(typeof x === 'string') {
console.log(x.splice(3, 1)); // 錯誤,'string'上不存在'splice'方法
}
// x 依然是 any 類型
x.foo(); // 合法
在這段代碼中,咱們首先聲明瞭一個any類型的變量x,隨後在運行時經過typeof運算符對x進行了類型檢查。若是x的類型爲string時,咱們就會嘗試調用被認爲是x的一個成員的splice方法。TypeScript語言服務能夠讀懂在條件語句中使用typeof的用法。TypeScript會自動推斷出x必定是string類型,而後告訴咱們splice方法不存於string類型上。這種特性被稱爲類型守護。
TypeScript容許使用type關鍵字聲明類型別名:
type PrimitiveArray = Array<string|number|boolean>;
type MyNumber = number;
type NgScope = ng.IScope;
type Callback = () => void;
可是不建議在一個大的項目團隊中使用這種別名,可維護性會下降。
環境聲明容許在TypeScript 代碼中建立一個不會被編譯到 JavaScript中的變量。這個特性是用來促進與現有 JavaScript 代碼、DOM(文檔對象模型),還有BOM(瀏覽器對象模型)結合而設計的。讓咱們看一個例子:
customConsole.log("A log entry!"); // 錯誤
若是你嘗試調用customConsole對象上的log方法,TypeScript會告訴咱們customConsole對象未被聲明:
// Cannot find name 'customConsole'
出現這種狀況並不使人意外。可是,有時候咱們但願調用一個未被定義的對象上的方法,好比window對象上的console方法。
console.log("Log Entry!");
var host = window.location.hostname;
當訪問 DOM 或 BOM 對象時,咱們沒有遇到錯誤,是由於這些對象已經在一個特殊的 TypeScript 文件(被稱爲聲明文件)中被聲明瞭。可使用declare操做符建立一個環境聲明。
在下面這段代碼中,咱們會聲明一個被customConsole對象實現的接口。而後使用declare操做符在做用域中增長一個customConsole對象:
interface ICustomConsole {
log(arg : string) : void;
}
declare var customConsole : ICustomConsole;
而後就能夠在沒有編譯錯誤的狀況下使用customConsole:
customConsole.log("A log entry!"); // 成功
TypeScript 默認包含一個名爲lib.d.ts的文件,它提供了像 DOM 這種 JavaScript 內置庫的接口聲明。
使用.d.ts結尾的聲明文件,是用來提升 TypeScript 對第三方庫和像 Node.js 或瀏覽器這種運行時環境的兼容性的。
運算符包括:算術運算符、比較運算符、邏輯運算符、位運算符、以及賦值操做符。
這些運算符在這裏再也不贅述,若是有開發的基礎的話,這些應該都會清楚。
三、流程控制語句
包含選擇語句、循環語句和分支語句
if 、if else 、?、switch case 、while 、do while 、for in(相似freach)、for循環,這些語句是咱們再熟悉不過的東東了,也再也不贅述了吧。
四、函數
關於函數,就像JavaScript同樣,TypeScript能夠經過具名或匿名方式建立,根據具體狀況,選擇合適的方式聲明便可。如:
function greet(name?:string):string{
return "Hi"+name;
}//這是一個帶有返回值的具名函數;
//匿名函數
var greet=function(name?:string):string{
return "Hi"+name;
}
若是不想使用函數的語法,還能夠有另外一種選擇,使用箭頭(=>)操做符並不適用function關鍵字,如:
var greet=(name?:string):string=>{
return "Hi"+name;
}
在這個例子中,咱們還能夠給greet變量添加上匹配匿名函數的類型:
var greet=(name?:string)=>string=function(name:string):string{
return "Hi"+name;
}
*注意:當處於類的內部時,若是使用箭頭函數(=>)語法將會改變this操做符的工做機制,會在後面的學習中詳細討論。
已經學習瞭如何將一個變量強制描述爲指定形式的函數。這在咱們使用回調函數時是十分有用的。
function sume(a:number,b:number,callback(result:number)=>void){
callback(a+b);
}
五、類
在ES6中添加了基於類的面向對象編程語法,因爲TypeScript是基於ES6的,因此咱們能夠開始使用基於類的面向對象的語法了。TypeScript的編譯器會負責將TypeScript代碼編譯爲兼容主流瀏覽器和平臺的JavaScript代碼。
class Person {
fullname: string;
constructor(firstname: string, lastname: string) {
this.fullname = firstname + " " + lastname;
}
hello(name?: string) {
if (name) {
return "Hi! " + name + "! My Name is " + this.fullname;
} else {
return "Hi! My Name is" + this.fullname;
}
}
}
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);// "Hi !Allen! My Name is Allen Choi";
var msgnull = person.hello();
alert(msgnull);//"Hi! My Name is Allen Choi"
在上面的例子中,咱們定義了一個Person類,有三個成員:一個fullname屬性,一個構造函數constructor和一個greet方法。當在TypeScript中聲明類時,全部的屬性和方法都是公共的。
當在對象內部訪問對象成員時,咱們都加上了this操做符,這代表這是一個成員訪問操做,咱們使用new操做符構造了一個Person實例,這會調用類的構造函數,按照定義對實例進行初始化。
爲了兼容ES3和ES5,TypeScript中的類會編譯爲JavaScript中函數
var Person = /** @class */ (function () {
function Person(firstname, lastname) {
this.fullname = firstname + " " + lastname;
}
Person.prototype.hello = function (name) {
if (name) {
return "Hi! " + name + "! My Name is " + this.fullname;
}
else {
return "Hi! My Name is" + this.fullname;
}
};
return Person;
}());
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);
var msgnull = person.hello();
alert(msgnull);
六、接口
在TypeScript中,可使用接口來確保類擁有指定的結構。
interface LoggerInterface {
log(arg: any): void;
}
class Logger implements LoggerInterface {
log(arg) {
if (typeof console.log === "function") {
console.log(arg);
} else {
alert(arg);
}
}
}
在這個例子中,咱們定義了一個LoggerInterface接口,和實現了一個Logger的類,Typescript也容許使用接口來約束對象,這樣能夠幫助咱們避免不少小錯誤。例以下面的例子中:
interface UserInterface {
name: string;
password: string;
}
var user: UserInterface = {
name:"",
pasword:"" //password 遺漏錯誤屬性
}
七、命名空間
命名空間,又稱內部模塊,被用於組織一些具備某些內在聯繫的特性和對象。命名空間可以使代碼結構更清晰,可使用namespace和export關鍵字,在TypeScript中聲明命名空間。
namespace Geometry {
interface VertorInterface {
/*...*/
}
export interface Vertor2dInterface {
/*...*/
}
export interface Vertor3dInterface {
/*...*/
}
export class Vertor2d implements VertorInterface, Vertor2dInterface {
/*...*/
}
export class Vertor3d implements VertorInterface, Vertor3dInterface {
/*...*/
}
}
var vector2dInstance: Geometry.Vertor2dInterface = new Geometry.Vertor2d();
var vector3dInstance: Geometry.Vertor3dInterface = new Geometry.Vertor3d();
在上面例子中,咱們聲明瞭一個包含了Vector2d、Vector3d類和VectorInterface、Vector2dInterface、Vector3dInterface接口的命名空間。
*注意:命名空間內的VectorInterface並無export關鍵字,因此在命名空間外部,咱們訪問不到它。
八、綜合運用
下面是一個使用了模塊、類、函數和類型註解的案例:
module Geometry{
export interface Vector2dInterface{
toArray(callback:(x:number[])=>void):void;
length():number;
normalize();
}
export class Vector2d implements Vector2dInterface{
private _x:number;
private _y:number;
constructor(x:number,y:number){
this._x=x;
this._y=y;
}
toArray(callback:(x:number[])=>void):void{
callback([this._x,this._y]);
}
length():number{
return Math.sqrt(this._x*this._x+this._y*this._y);
}
normalize(){
var len=1/this.length();
this._x*=len;
this._y*=len;
}
}
}
var vector:Geometry.Vector2dInterface=new Geometry.Vector2d(2,3);
vector.normalize();
vector.toArray(function(vectorasArray:number[]){
alert('x:'+vectorasArray[0]+'y:'+vectorasArray[1]);
})
4、小結
這一部分的內容主要是介紹了一些關於TypeScript的基礎知識,相信有開發經驗的人對這些並不感冒,無論你是用了兩分鐘看完了,仍是用了20分鐘看完了,但願你能有一點點的收穫,內容有書本上的內容,也有網上摘的,若有不對的地方,請多包涵指正。從頭看到尾,或許你愈來愈感受它的語法以及一些特性,像極了C#,對於.Net 開發人員來講應該是再熟悉不過了。後面的內容會持續更新,也但願本身能堅持下來吧。