typescript安裝、編譯、資料型別、函式宣告、ES5中的類、TS中的類、介面、泛型、裝飾器
Typescript安裝
npm installl -g typescript
編譯成js
tsc aaa.ts
執行該命令後會自動生成js檔案
在VScode中設定儲存後自動編譯
1.生成tscconfig.json檔案
tsc --init
2.修改tscconfig.json檔案中outDir:'/js',此後生成的js檔案會存入js的資料夾中
3.VScode編輯器裡
任務-執行任務,點選監視tsconfig.json
資料型別
1
.布林型別 boolean
2
.數字型別 number
3
.字串型別 string
4
.陣列型別 array
let ar:number[]=[1,2,3]
5
.元組型別 tuple
let ar:[string,number,number]=["1",2,3]
實際上就是一個允許不同資料型別的陣列
6
.列舉型別 enum
enum color {red,green,blue}
let c:color=color.green
console.log(c)//1
7
.任意型別 any
window.onload=function(){
let box:any=document.getElementById("div")//獲取元素時,元素物件型別為any
box.innerHTML="hello"
}
8
.null和undefined
var num:number//num未進行初始化,編譯報錯
console.log(num)
var num:number|null|undefined//num如果未初始化,賦值為null或undefined
console.log(num)
9
.void型別
function run():void{//該方法無返回值
console.log("run")
}
10
.never型別
哪些永遠不存在的值的型別,返回never的函式必須存在無法達到的終點
//這是官方文件的例子
// 返回never的函式必須存在無法達到的終點
function error(message: string): never {
throw new Error(message);
}
// 推斷的返回值型別為never
function fail() {
return error("Something failed");//會丟擲錯誤
}
// 返回never的函式必須存在無法達到的終點
function infiniteLoop(): never {
while (true) {
}
}
函式宣告
1
.普通方式和匿名函式方式宣告
//普通方式
function run():void{
console.log("run")
}
run()//輸出run
//匿名函式方式
var run1=function():void{
console.log("run")
}
run1()//輸出run
2
.引數、可選引數、預設引數
//引數
function getinfo(name:string,age:number):string{
return `${name}--${age}`
}
console.log(getinfo("aaa",25))//輸出aaa--25
//可選引數,必須配置到引數的最後面
function getinfo1(name:string,age?:number):string{
return `${name}--${age}`
}
console.log(getinfo1("aaa"))//輸出aaa--undefined
//預設引數
function getinfo2(name:string,age:number=20):string{
return `${name}--${age}`
}
console.log(getinfo2("aaa"))//輸出aaa--20
可選引數這裡和js完全不同,如果時可選引數必須用“?”標記出來,否則會報錯。而在js中不傳第二個引數時不會報錯,第二個引數會預設為undefined。
3
.剩餘引數,“...”接收傳過來的所有引數
function sum(...result:number[]):number{
var sum=0
for(var i=0;i<result.length;i++){
sum+=result[i]
}
return sum
}
console.log(sum(1,2,3,4))//輸出 10
4
.解構用於函式宣告
type C = { a: string, b?: number }
function f({ a, b }: C): void {
console.log("a:",a,"b:",b)
}
f({a:"qwe"})//輸出 a: qwe b: undefined
5
.方法過載
function getInfo(name:string):string
function getInfo(name:string,age:number):string
function getInfo(name:string,age?:any):any{
if(age){
return "我叫:"+name+"我的年齡是:"+age
}else{
return "我叫:"+name
}
}
console.log(getInfo("zhang"))//輸出 我叫:zhang
console.log(getInfo("zhang",18))//輸出 我叫:zhang我的年齡是:18
//console.log(getInfo(123)) 這樣寫是錯誤的
ES5中類
1
.定義
function person(name,age){
this.name=name
this.age=age
this.run=function(){
console.log(this.name+'在運動')
}
}
person.getinfo=function(){
console.log("我是靜態方法")
}//定義靜態方法
//原型鏈上定義屬性、方法
person.prototype.sex="男"//原型鏈上屬性會被多個例項共享
person.prototype.work=function(){
console.log(this.name+"在工作")
}
person.getinfo()//執行靜態方法,輸出 我是靜態方法
p=new person("zhang",18)
p.run()//執行物件方法,輸出 zhang在運動
p.work()//執行原型鏈方法,輸出 zhang在工作
2
.繼承
1)物件冒充實現繼承
function web(name,age){
person.call(this,name,age)//物件冒充實現繼承
}
var w=new web("zhang",18)
w.run()//輸出 zhang在運動
w.work()//報錯,物件不支援work屬性或方法
只可繼承建構函式里的屬性和方法,無法繼承原型鏈裡的屬性和方法
2)原型鏈實現繼承
function web(name,age){
}
web.prototype=new person("zhang",18)
var w=new web()
w.run()//輸出 zhang在運動
w.work()//輸出 zhang在工作
既可繼承建構函式里的屬性和方法,又可以繼承原型鏈裡的屬性和方法。問題也很明顯,例項化時子類無法給父類傳參
3)物件冒充組合原型鏈實現繼承
function web(name,age){
person.call(this,name,age)
}
web.prototype=person.prototype
var w=new web("zhang",18)
w.run()//輸出 zhang在運動
w.work()//輸出 zhang在工作
既可繼承建構函式里的屬性和方法,又可以繼承原型鏈裡的屬性和方法,解決原型鏈繼承中的問題
TS中的類
1
類的定義
class person{
name:string
constructor(name:string){
this.name=name
}
run():void{
console.log(`${this.name}在跑步`)
}
}
var p=new person('zhang')
p.run()//輸出 zhang在跑步
2
類的繼承
class worker extends person{
constructor(name:string){
super(name)
}
work():void{
console.log(`${this.name}在工作`)
}
}
var w=new worker('huan')
w.run()//輸出 huan在跑步
w.work()//輸出 huan在工作
3
類的修飾符
public 公有,在類、子類裡外都可訪問
protected 保護型,在類、子類裡可訪問,在類外不可訪問
private 私有型,在類裡可訪問,字類裡、外都不可訪問
4
抽象類
abstract class animal{
public name:string
constructor(name:string){
this.name=name
}
abstract eat():any//定義抽象方法,其字類必須實現該方法
}
class dog extends animal{
constructor(name:string){
super(name)
}
eat():any{
console.log(`${this.name}在吃狗糧`)
}
}
var d=new dog('小黑')
d.eat()//輸出 小黑在吃狗糧
介面
為達到規範,定義的一種約束
1
.約束
//對函式引數的約束
interface config{
type:string;
url:string;
data?:string;
dataType:string;
}
function ajax(config:config){
var xhr=new XMLHttpRequest()
xhr.open(config.type,config.url,true)
xhr.send(config.data)
xhr.onreadystatechange=function(){
if(xhr.readyState==4&&xhr.status==200){
console.log("success")
if(config.dataType=='json'){
console.log(JSON.parse(xhr.responseText))
}else{
console.log(xhr.responseText)
}
}
}
}
ajax({
type:'get',
data:'name=zhang',
url:'http://a.itying.com/api/productlist',
dataType:'json'
})
//對函式的約束
interface encrypt{
(key:string,value:string):string
}
var md5:encrypt=function(key:string,value:string):string{
return key+value
}
console.log(md5('zhang','huan'))
//對陣列的約束
interface userarr{
[index:number]:string
}
var arr:userarr=['aaa','bbb']
console.log(arr[0])
//對物件的約束
interface userobj{
[index:string]:string
}
var obj:userobj={
name:'zhang'
}
console.log(obj.name)
//對類的約束
interface animal{
name:string
eat(str:string):void
}
class dog implements animal{
name:string
constructor(name:string){
this.name=name
}
eat(){
console.log(`${this.name}吃狗糧`)
}
}
var xiaohei=new dog("小黑")
xiaohei.eat()
class cat implements animal{
name:string
constructor(name:string){
this.name=name
}
eat(food:string){
console.log(`${this.name}吃${food}`)
}
}
var xiaohua=new cat("小花")
xiaohua.eat("耗子")
2
繼承
//官方文件的多繼承例子
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = <Square>{};//例項化一個物件
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
泛型
在定義函式、介面或類的時候,不預先設定其型別,而在呼叫時在指定型別
function go<T>(arg:T):T{
console.log(arg)
return arg
}
go('go,go,go……')//輸出 gp,go,go……
裝飾器
1
修改tsconfig.json檔案,使得VS支援裝飾器功能
"experimentalDecorators": true,
2
使用
//類裝飾器
function logclass(params:any) {//params就是當前類
params.prototype.apiurl="動態擴充套件屬性"//給類擴充套件屬性
params.prototype.run=function(){//給類擴充套件方法
console.log("這是擴充套件的run方法")
}
}
@logclass
class httpclient{
}
var h:any=new httpclient()
console.log(h.apiurl)//輸出 動態擴充套件屬性
h.run()//輸出 這是擴充套件的run方法
//裝飾器工廠
function logclass(params:any) {//外部引數
return function(target:any){//target是當前類
console.log(params)
console.log(target)
}
}
@logclass("hello")//可傳參
class httpclient{
}
var h=new httpclient()
//輸出 hello
//輸出 f httpclient() {
// }
//裝飾器修改類的建構函式
function logclass(params:any):any {
return class extends params{
constructor(){
super(name)
this.name="修改後的建構函式"
console.log(this.name)
}
}
}
@logclass//可傳參
class httpclient{
name:string|undefined
constructor(){
this.name="修改前的建構函式"
console.log(this.name)
}
}
var h=new httpclient()
//輸出 修改前的建構函式
//輸出 修改後的建構函式
//屬性裝飾器
function logproperty(params:any){//params外部引數
return function(target:any,attr:any){//target是原型物件,attr是物件的屬性,這裡會將修飾的屬性自動傳入
console.log(target)
console.log(attr)
target[attr]=params
}
}
class httpclient{
@logproperty("xxx.com")
name:string|undefined
constructor(){
}
}
var h=new httpclient()
console.log(h.name)
//輸出 {constructor: ƒ}
//輸出 name
//輸出 xxx.com
//方法裝飾器
//傳入3個引數分別接收:類的原型物件、成員名字、成員屬性描述符
function get(params:any):any {
return function(target:any,methodname:any,desc:any){
console.log(target)
console.log(methodname)
console.log(desc)
}
}
class httpclient{
name:string|undefined
constructor(){
this.name="zhanghuan.top"
console.log(this.name)
}
@get("abcdefg")//放在方法上
getdata(){
console.log(this.name)
}
}
var h=new httpclient()
//輸出 {getdata: ƒ, constructor: ƒ}
//輸出 getdata
//輸出 {value: ƒ, writable: true, enumerable: true, configurable: true}
//輸出 zhanghuan.top
3
裝飾器執行順序
屬性>方法>方法引數>類