JS缺點:
1.舊JS 是弱類型語言,一個變量先后可以保存不同類型的數據(不可靠)
2.舊JS 是解釋執行語言,一邊解釋,一邊執行。一些低級錯誤無法提前檢查和預警
3.舊JS 對對象要求不嚴格,開發人員想怎么寫就怎么寫,不便於大項目協作
TypeScript介紹:
是JavaScript 的一個超集(在原有的JS 語言基礎上封裝了一層更嚴格的規范)
支持ECMAScript 6 標准
TypeScript 由微軟開發
設計目的是開發大型應用

注意: TS 不能被瀏覽器直接執行,但是TS 可以變異成純 JS ,編譯出來的JS 可以運行在任何瀏覽器或 nodejs 上。
TS 的新特性:類型檢查、編譯時錯誤檢查、接口、訪問修飾符、模塊
TS的安裝使用:
1. 全局安裝TS 語言的編譯器:npm i -g typescript
2. 用 vscode (vscode需要高版本)打開項目文件夾,右鍵選擇在終端中打開,在終端中輸入:tsc -init (說明tsc 是ts 語言的編譯器,c 是compile 的意思,編譯)
最后就是在當前項目文件夾中生成了tsconfig.json 文件,其中保存的是將ts 編譯為js 時所需的配置,比如:
-- target:“ES5” 在將ts 文件編譯為js 文件時,編譯為ES5 的版本,兼容更多瀏覽器
-- module:“commenJS” 將來ts 文件中模塊化開發所采用的標准
-- strict:true 將ts 文件編譯js 文件時,自動啟用嚴格模式
接下來就可以新建自己的ts 文件(first.ts):
//規定:a 變量將來只能保存數字類型的值 let a:number = 10 console.log(a)
再編譯ts 文件為js 文件:打開命令行窗口,輸入tsc first.ts
結果,tsc 編譯器將.ts 文件的內容翻譯為等效的js 文件,保存在ts 文件旁邊的同名first.js文件中:
// first.js "use strict"; var a = 10; console.log(a); // 10
以上操作在實際項目中不可能每操作一步就去編譯一次,所以,要配置自動編譯:
在 vscode 中選擇“終端”--“運行生成任務”--“tsc:監視”
配置后只要一自改ts文件,一旦保存就會自動編譯,自動創建js 文件
不輸入命令,運行js 文件:
1.先打開要運行的js 文件
2.點左邊小蟲 + 三角圖標
3.點運行和調試
4.選擇node.js
5.查看執行結果
ts中的變量和聲明:
變量 ==》
1.舊的js 是弱類型語言,一個變量先后可以保存不同類型的數據(不可靠)
今后,只要在ts 中聲明變量,都必須用“:數據類型”來規定
2.標准語法:var 或 const 或 let 變量名:數據類型 = 初始值
結果:將來這個變量只能保存規定的數據類型
比如 var a = 10 要換成 let a:number = 10; // 正確
a = “hello” 報錯:不能將類型“string”分配給類型“number”
ts 能夠寫在冒號后的數據類型有哪些呢?
1.基本類型:boolean、number、string
2.數組:兩種寫法,結果一樣
2-1.let 數組名:數據類型 [] = [值1,值2,...] 例如 let arr:string[] = ['a','b','c']
2-2.let 數組名:Array <數據類型> = [值1,值2,...]
3.any:可以匹配任何數據類型(對於不能確定的數組類型可以使用any定義)例如 var arr2 = ['a',1,true]
函數
1.既沒有參數,又沒有返回值的函數,與普通 js 寫法一樣
2.如果函數有返回值

3.如果函數有參數

4.既有形參,又有返回值

5.可選參數(一個形參可能有也可能沒有)
?表示參數可以沒有。將來如果沒有傳入這個參數值,則參數值默認為undefined

6.默認值

7.實參值個數不確定

// 無返回值的函數 const intr = () => { console.log(`I'm tom`) // I'm tom } intr(); // 帶返回值的函數 const intr2 = ():string => { retrun `I'm tom` } console.log(intr2()) // I'm tom // 帶參數的函數 const intr3 = (sname:string,sage:number):string => { retrun `I'm ${sname},I'm ${sage}` } console.log(intr3('tom',12)) // I'm tom,I'm 12 // 不確定參數 const intr4 = (sname:string,sage?:number):string => { if(sage === undefined){ retrun `I'm ${sname}` }else{ retrun `I'm ${sname},I'm ${sage}` } retrun `I'm ${sname},I'm ${sage}` } console.log(intr4('tom',10)) // I'm tom,I'm 10 console.log(intr4('tom')) // I'm tom // 默認值的參數 const intr5 = (sname:string,sage:any = '未知') => { console.log(`I'm ${sname},年齡:${sage}`) } intr5('tom',15) // I'm tom,年齡:15 intr5('tom') // I'm tom,年齡:未知 // 求和函數 const add = (...arr:number[]):number => { return arr.reduce((box,elem) => box+elem,0) } console.log(add(1,2,3)) // 6 console.log(add(1,2,3,4,5)) // 15
重載
舊 JS 中,重載只定義一個函數,在函數內根據傳入的參數不同,執行不同的邏輯
function pay(){ if(arguments.length === 0){ 手機支付 } else if (arguments.length === 1){ 現金支付 } else { 刷卡支付 } } pay() pay(100) pay("6553 1234","123456")
TS中:
1.先要定義多個同名函數的聲明,只要形參列表不同即可。但是不要實現函數體
function 函數名():void;
function 函數名(形參:數據類型):void;
注意:這里只是不同重載版本的聲明,不包含函數定義
void 代表這個函數沒有返回值
如果函數有返回值,則必須將void 改為返回值的具體類型
2.定義一個可實際執行多種任務的函數支持上方多種重載的情況 
function pay():void; function pay(money:number):void; function pay(cardId:string,pwd:string):void; //括號里的a和b 也可以寫成(...arr:any[])形式,判斷arr.length打印對應的arr[index]值 function pay(a?:any,b?:any){ if(a === undefined){ console.log(`手機支付`) }else if(b === undefined){ console.log(`現金支付,收您${a}元`) }else{ console.log(`刷卡支付,從您卡號:${a} 扣款成功`) } } pay() // 手機支付 pay(100) // 現金支付,收您100元 pay('123456') //刷卡支付,從您卡號:123456 扣款成功
CLASS
定義class:

// 定義一個學生類型 class Student{ sname:string = ''; sage:number = 0; constructor(sname:string,sage:number){ this.sname = sname; this.sage = sage; } intr(){ console.log(`I'm ${this.sname},I'm ${this.sage}`) } } var tom = new Student("tom",11) as any; // ts中默認對象限制對象用中括號來訪問的,所以如果一個對象需要去遍歷,name需要添加as any 防止用中括號讀取屬性值時報錯 console.log(tom); for(var key in tom){ console.log(`${key}:${tom[key]}`) } tom.intr()
兩種類型間繼承
子類型class:

// 類型繼承 // 定義父類型 class Enemy{ x:number = 0; y:number = 0; constructor(x:number,y:number){ this.x = x; this.y = y; } fly(){ consle.log(`飛到x=${this.x},y=${this.y}位置`) } }
// 定義子類型 class Plane extends Enemy{ score:number = 0; constructor(x:number,y:number,score:number){ super(x,y); this.score = score } getScore(){ console.log(`擊落敵機,得${this.score}分`) } } var p1 = new Plane(50,100,5) as any;
console.log(p1); for(var key in p1){ console.log(`${key}:${p1[key]}`) } p1.fly(); p1.getScore();
訪問修飾符
class中的所有成員無論在class內,還是在子類型內,還是全局,都可用“this.屬性名” 或 “父對象.屬性名” 方式訪問,沒有限制。
但是有些數據,不想任所有人輕易都知道。舊的js 中就無法控制,所以ts 就產生了訪問修飾符,是專門修飾一個屬性或一個方法的可用范圍的關鍵字(控制訪問的范圍),例如:訪問控制修飾符 === 屬性名:數據類型 = 初始值
訪問修飾符有3種:
1. public 公有(默認),表示子類型和類外部都可以訪問到的類型成

2. protected 受保護,表示只有父子類型范圍內才能使用,外部不能用

3. private 私有,表示僅class 內可用,子類型和外部都不能用

// 公有 class Father{ moneyPublic:string = "爸爸可公開的錢"; fatherPay(){ console.log(`爸爸花${this.moneyPublic}買了包煙`) } } class Son extends Father{ sonPay(){ console.log(`孩子花${this.moneyPublic}買了玩具`) } } var f = new Father(); f.fatherPay(); // 爸爸花爸爸可公開的錢買了包煙 var s = new Son(); s.sonPay(); // 孩子花爸爸可公開的錢買了玩具 console.log(`媽媽花${f.moneyPublic}買了包`) // 媽媽花爸爸可公開的錢買了包 // 繼承 class Father{ // 上面因為 public 是默認屬性,所以可以不寫 protected moneyPublic:string = "爸爸和兒子的小金庫"; fatherPay(){ console.log(`爸爸花${this.moneyPublic}買了包煙`) } } class Son extends Father{ sonPay(){ console.log(`孩子花${this.moneyPublic}買了玩具`) } } var f = new Father(); f.fatherPay(); // 爸爸花爸爸和兒子的小金庫買了包煙 var s = new Son(); s.sonPay(); // 孩子花爸爸和兒子的小金庫買了玩具 console.log(`媽媽花${f.moneyPublic}買了包`) // 報錯 // 私有 class Father{ private moneyPublic:string = "爸爸的私房錢"; fatherPay(){ console.log(`爸爸花${this.moneyPublic}買了包煙`) } } class Son extends Father{ sonPay(){ console.log(`孩子花${this.moneyPublic}買了玩具`) } } var f = new Father(); f.fatherPay(); // 爸爸花爸爸的私房錢買了包煙 var s = new Son(); s.sonPay(); // 報錯 console.log(`媽媽花${f.moneyPublic}買了包`) // 報錯
接口
用來規范按照要求實現程序結構,只要希望別人一定按照你的要求實現程序時,都用接口規范

// 定義學生class 的接口規范,並定義學生class 遵守接口規范 // 上級規定 interface IStudent{ sname:string; sage:number; intr():void; } // 開發人員 class Student2 implements IStudent{ sname:string = ""; sage:number = 0; constructor(sname:string,sage:number){ this.sname = sname; this.sage = sage; } intr():void{ console.log(`I'm${this.sname},I'm${this.sage}`) }; } var tom2 = new Student2('tom',11); console.log(tom2); // {sname:'tom',sage:11} tom.intr(); // I'm tom,I'm 11
模塊化開發
舊JS 中,所有js 文件要幾種引入到html 文件中才能運行,ts 中哪個文件想要使用另一個文件內容,直接引入即可,不用經過任何第三方

// 只拋出一個文件 interface IStudent{ sname:string; sage:number; intr():void; } export default IStudent; // 引入 import ISsudent from "./拋出文件名稱" class Student implements IStudent{ sname:string = ''; sage:number = 0; intr():void{ console.log('打印.....') } } // 拋出多個 interface IStudent{ sname:string; sage:number; intr():void; } class Enemy{ x:number = 0; y:number = 0; constructor(x:number,y:number){ this.x = x; this.y = y; } fly(){ consle.log(`飛到x = ${this.x},y = ${this.y} 位置`) } } export {IStudent,Enemy}; // 引入(只引入文件中的其中一個) import { IStudent } from "./拋出的文件名稱" class Student implements IStudent{ sname:string = ''; sage:number = 0; intr():void{ console.log('打印.....') } } // 其他文件中引入另一個 import { Enemy } from "./拋出的文件名稱" class Plane extends Enemy{ score:number = 0; constructor(x:number,y:number,score:number){ super(x,y); this.score = score; } }
