一、 函數
1. 定義函數
1. 函數聲明
//?爲可選參數 可選參數必須配置在最後面
//可用默認參數,但不能和?用在一起
function fun1(name:string='li', age?:number):string{ //規定返回值爲string類型
return `${name}--${age}`
}
console.log(fun1('san'))
console.log(fun1('san', 10))
2. 匿名函數
let fun2 = function():void{ //無返回值
console.log(11)
}
3. 三點運算符的應用
function sum(...res:number[]):number{ //需要存在一個數組中
let sum:number = 0
for(let i = 0; i<res.length; i++){
sum += res[i]
}
return sum
}
console.log(sum(1,2,3))
function ali(num1:number,...num2:number[]):number{ //三點運算符要放在最後面
return num1
}
//數組第一個值放在num1中
console.log(ali(1,2,3))
二、 類
1. 類的定義
class Person{
name:string
constructor(n:string){ //構造器 實例化類的時候觸發的方法
this.name = n
}
getName():string{
return this.name
}
setName(name:string):void{
this.name = name
}
}
let p = new Person('li')
console.log(p.getName())
p.setName('zhang')
console.log(p.getName())
2. 類的繼承
class Person{
name:string
constructor(n:string){ //構造函數 實例化類的時候觸發的方法
this.name = n
}
getName():string{
return this.name
}
setName(name:string):void{
this.name = name
}
}
//繼承
class Web extends Person{
constructor(name:string){
super(name) //super表示調用父類的構造函數 constructor
//將形參name存的值傳到Person構造器的n中
}
man(){ //不能用this.man = function(){}
console.log('man')
}
}
let w = new Web('wang')
console.log(w.getName())
w.man()
3. 類修飾符
1. 三種類修飾符
- public: 公有 在類裏面 子類 類外面都可以訪問
- protected: 保護類型 在類裏面 子類裏面可以訪問
- private: 私有 類裏面可以訪問
2. 修飾符實例
class Person{
public age:number = 20
protected name:string
private sex:string = 'male'
constructor(age:number, name:string, sex:string){ //構造函數 實例化類的時候觸發的方法
this.name = name
this.age = age
this.sex = sex
}
getName():string{
return this.name
}
setName(name:string):void{
this.name = name
}
getAge():void{
console.log(this.age) //類內訪問
}
}
//繼承
class Web extends Person{
constructor(age:number, name:string, sex:string){
super(age, name, sex)
}
work(){
console.log(this.name) //訪問protected name
// console.log(this.sex) 錯 不能訪問
}
}
let p = new Person(20, 'li', 'male')
console.log(p.age) //訪問public age
// console.log(p.name) 錯
// console.log(p.sex) 錯
let w = new Web(30, 'wang', 'female')
w.work()
4. 靜態方法 實例方法 靜態屬性
class Per{
public name:string = 'wang'
static age:number = 20
constructor(name:string){
this.name = name
}
run(){ //實例方法 只能通過實例調用
console.log(`${this.name}在運動`)
}
static work(){ //靜態方法不能直接調用類裏的屬性,只能調用靜態屬性
console.log(`我的年齡是${this.age}`)
}
}
let p = new Per('wang')
p.run()
Per.work() //靜態方法可以直接調用
5. 多態的表現-重載與重寫
1. 重載
1. 什麼是重載
就是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之爲重載函數或者方法
2. 重載的作用
不用爲了對不同的參數類型或參數個數,而寫多個函數。多個函數用同一個名字,但參數表,即參數的個數或(和)數據類型可以不同,調用的時候,雖然方法名字相同,但根據參數表可以自動調用對應的函數
3. 重載實例
function getInfo(name:string):string
function getInfo(age:number):string
function getInfo(str:any):any{
if(typeof str === 'string') return '我叫 ' + str
else return '我的年齡是 ' + str
}
console.log(getInfo('zhangsan'))
console.log(getInfo(20))
//console.log(getInfo(true)) //錯 沒有布爾型的函數聲明
//可選參數的重載
function get(name:string):string
function get(name:string, age:number):string
function get(name:any, age?:any):any{
if(age) return '我叫 ' + name + '我的年齡是 ' + age
else return '我叫 ' + name
}
console.log(get('li'))
// console.log(get(123)) 錯誤
console.log(get('li', 20))
// console.log(get('li', true)) 錯誤
2. 重寫
1. 什麼是重寫
- 發生在父類與子類之間
- 方法名,參數列表,返回類型(除過子類中方法的返回類型是父類中返回類型的子類)必須相同
- 訪問修飾符的限制一定要大於被重寫方法的訪問修飾符(public>protected>private)
- 用子類中的方法代替父類中同名方法
2. 重寫實例
class Animal{
name:string
constructor(name:string){
this.name = name
}
eat(){
console.log('吃的方法')
}
}
class Dog extends Animal{
constructor(name:string){
super(name)
}
eat(){
return this.name + '吃骨頭'
}
}
let d = new Dog('狗狗')
d.eat()
3. 抽象類
1. 什麼是抽象類
- 抽象類它是提供其他類繼承的基類,不能直接被實例化 用abstract關鍵字定義抽象類和抽象方法,
- 抽象類中的抽象方法不包含具體實現並且必須在派生類中實現,抽象方法只能放抽象類中
- 用抽象類和抽象方法定義標準
2. 抽象類實例
abstract class Animal{
public name:string
constructor(name:string){
this.name = name
}
abstract eat():any
}
// let a = new Animal() 錯誤 抽象類不能直接被實例化
class Dog extends Animal{
//抽象類的子類必須實現抽象類中的抽象方法
constructor(name:string){
super(name)
}
changeName(){
this.name = '阿貓阿狗'
console.log(this.name)
}
eat(){
console.log(this.name + '吃骨頭')
}
}
let d = new Dog('狗狗')
d.eat()
d.changeName()
6. 接口 約束作用
1. 屬性接口
function printLabel(label:string):void{ //約束傳入字符串且無返回值
console.log('print')
}
function print(labelInfo:{label:string}):void{
console.log('labelInfo')
}
// print('haha') 錯誤
// print({name: 'haha'}) 錯誤
print({label: 'wang'})
//interface關鍵字定義接口
interface FullName {
firstName: string
secondName?: string //可選屬性
}
function printName(name:FullName){ //必須傳入對象firstName secondName
console.log(name.firstName + name.secondName)
}
// printName(20,'zhang','san') 錯 只能傳兩個字符串
let obj={
age: 20,
secondName: 'san',
firstName: 'zhang' //順序可以顛倒
}
printName(obj) //可以
//接口實例作用 封裝 ajax
//約束了屬性的名字和類型
interface Config{
type:string
url:string
data?:string
dataType:string
}
function ajax(config:Config){
let 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')
//JSON.stringify()的作用是將 JavaScript 對象轉換爲 JSON 字符串,而JSON.parse()可以將JSON字符串轉爲一個對象。
if(config.dataType === 'json') JSON.parse(xhr.responseText)
else console.log(xhr.responseText)
}
}
}
ajax({
type:'get',
data:'name=zhangsan',
url:'www.baidu.com',
dataType:'json'
})
2. 函數類型接口
//對方法傳入的參數及返回值進行約束
interface encrypt{
(key:string, value:string):string
}
//名可以不同 但是類型得相同
let md5:encrypt = function(keys:string, values:string):string{
return keys + values
}
console.log(md5('name', 'zhang'))
3. 可索引接口
//對數組、對象的約束
var arr:number[] = [222,333] 正常定義數組的方式
var arr1:Array<string> = ['222','333']
interface UserArr{
[index:number]:string //number是索引值的數據類型 string是value的數據類型
}
let arr:UserArr = ['aaa', 'bbb']
console.log(arr[0])
interface UserObj{
[index:string]:string | number
}
let obj:UserObj = {name:'張三', age:20}
4. 類類型接口
//對類的約束 和 抽象類有點類似
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 + '吃骨頭')
}
}
let d = new Dog('狗狗')
d.eat()
class Cat implements Animal{
name:string
constructor(name:string){
this.name = name
}
eat(food:string){ //沒有參數也可以
console.log(this.name + '吃骨頭')
}
}
let c = new Cat('喵喵')
c.eat('food')
5. 接口繼承接口
interface Animal{
getName():void
}
interface Person extends Animal{
getFood():void
}
class Web implements Person{
name:string
food:string
constructor(name:string, food:string){
this.name = name
this.food = food
}
getName(){
console.log(this.name)
}
getFood(){
console.log(this.name + '吃' + this.food)
}
}
let w = new Web('小李', '米')
w.getFood()
6. 繼承結合接口
class Pro{
work:string
constructor(work:string){
this.work = work
}
}
class Code extends Pro implements Person{
constructor(name:string, food:string, work:string){
super(work)
}
getName(): void {
}
getFood(): void {
}
}
7. 泛型
1. 泛型函數
function getData<T>(value:T):T{
return value
}
getData<number>(123)
getData<string>('123')
//或者可以將返回值設爲any
function getNum<T>(value:T):any {
return '1233'
}
getNum<number>(123)
2. 泛型類
class MinClass<T>{
public list:T[] = []
add(num:T){
this.list.push(num)
}
min():T{
let minNum = this.list[0]
for(let i=0;i<this.list.length;i++){
if(minNum > this.list[i]){
minNum = this.list[i]
}
}
return minNum
}
}
let m = new MinClass<number>() //實例化類並且指定了T代表的類型是number
3. 泛型接口
//寫法1
interface ConfigFn{
<T>(value:T):T
}
let getData:ConfigFn = function<T>(value:T):T{
return value
}
getData<string>('12')
//寫法2
interface Config<T>{
(value:T):T
}
function getData<T>(value:T):T{
return value
}
let myGetData:Config<string> = getData
myGetData('2000')
4. 把類作爲參數來約束數據傳入的類型
//平常做法
class User{
username:string | undefined
password:string | undefined
}
class MysqlDB{
add(user:User):boolean{
console.log(user)
return true
}
}
let u = new User()
u.username = '張三'
u.password = '123'
let db = new MysqlDB()
db.add(u)
class User{
username:string | undefined
password:string | undefined
}
class MysqlDB<T>{
add(info:T):boolean{
console.log(info)
return true
}
}
let u = new User()
u.username = '張三'
u.password = '123'
let db = new MysqlDB<User>() //驗證
db.add(u
8. 裝飾器
1. 什麼是裝飾器
- 裝飾器 可以注入到類 方法 屬性參數上來擴展類 屬性 方法 參數的功能
- 裝飾器寫法 普通裝飾器(無法傳參) 裝飾器工場(可傳參)
2. 類裝飾器
//在類聲明之前被聲明 緊靠着類聲明
//普通裝飾器
function logClass(params:any){
console.log(params) //params就是當前類
params.prototype.apiURL = '動態擴展的屬性'
params.prototype.run = function(){
console.log('這是一個run方法')
}
}
@logClass
class HttpClient{
constructor(){}
getData(){}
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.run()
//裝飾器工廠
function logClass(params:any){
return class extends params{
apiURL:string = '修改後的api'
getData(){
this.apiURL = this.apiURL + '--'
console.log(this.apiURL) //如果裏面
}
}
}
@logClass
class HttpClient{
public apiURL:string | undefined
constructor(){
this.apiURL = '修改前的api'
}
getData(){
console.log(this.apiURL)
}
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.getData()
3. 屬性裝飾器
function logProperty(params:any){
return function(target:any, attr:any){
console.log(target) //指向類
console.log(attr) //指向要修飾的屬性
target[attr] = params
}
}
class HttpClient{
@logProperty('修改後的api')
public url:any | undefined
constructor(){}
getData(){
console.log(this.url)
}
}
let p = new HttpClient()
p.getData()
4. 方法裝飾器
function get(params:any){
return function(target:any, methodName:any, desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
target.apiURL = '新增api'
target.run = function(){
console.log('新增方法')
}
}
}
class HttpClient{
public url:any | undefined
constructor(){}
@get('www.baidu.com')
getData(){
console.log(this.url)
}
}
let http:any = new HttpClient()
console.log(http.apiURL)
http.run()*/
//方法裝飾器將數組全部變成字符串
function get(params:any){
return function(target:any, methodName:any, desc:any){
console.log(target)
console.log(methodName)
console.log(desc)
let oMethod = desc.value
desc.value = function(...args:any[]){ //這麼寫是替換desc.value
args = args.map((value)=>{ //而不是重寫
return String(value)
})
console.log(args)
oMethod.apply(this, args) //重寫
}
}
}
class HttpClient{
public url:any | undefined
constructor(){}
@get('www.baidu.com')
getData(...args:any[]){
console.log(args)
console.log('我是getData裏面的方法')
}
}
let http:any = new HttpClient()
http.getData(123, 'xx')
5. 參數裝飾器
function logParams(params:any){
return function(target:any, methodName:any, paramsIndex:any){
console.log(params)
console.log(target)
console.log(methodName)
console.log(paramsIndex)
target.apiURL = params
}
}
class HttpClient{
public url:any | undefined
constructor(){}
getData(@logParams('xx') uuid:any){
console.log(uuid)
}
}
let http:any = new HttpClient()
http.getData('123')
console.log(http.apiURL)
6. 裝飾器注意點
- 裝飾器執行順序 屬性>方法>方法參數>類
- 同一種裝飾器由後向前 後近向遠執行