前段時間學習了ts,做了一些筆記,想着還是發到博客上來!
console.log('你好呀!TS')
function getData() {
}
let str: string = '你好TS'
console.log(str)
let arr:number[] = [1,2,3];
console.log(arr);
let arr2:Array<string> = ['1', '2', '3'];
console.log(arr2)
// 元組類型 給數組中某個元素指定指定的類型
let arr:[number, string] =
[1,'456'] console.log(arr)
1. 枚舉類型
enum Flag {
success = 1,
error = 0
};
let s: Flag = Flag.success;
console.log(s) //打印出1
enum Color {blue,red,yellow,black};
let c: Color = Color.yellow;
console.log(c) // 2如果標識符沒有賦值,它的值對應的就是下標
2. 任意類型 any; 空類型:null; undefined void:啥也不是
3. never類型:是其他類型(包括null和undefined)的子類型,代表從不會出現的值
定義函數的方法,在函數傳參的時候指定類型和
輸出指定類型;1.可選參數age?:number;可選參數age: number=20;
function func1(name: string, age:number):number {
return 123
}
const func2 = function():string {
return '123'
}
若沒有返回值:
function func3(name: string, age: number): void {
console.log('這是一個沒有返回值的函數')
}
函數的重載,同名的函數傳入不同的參數得到不同的結果es5中出現同名方法,下面的會替代上面的方法;但是在TS中允許同名函數.
ts中的重載:
function getInfo(name: string): string;
function getInfo(age: number): number;
function getInfo(str:any):any {
if(typeof str==='string'){
return '名字:'+str
}else {
return '年齡:'+123 //返回一個數
}
}
getInfo('zhangsan')
es5中的繼承,冒充(Person.call(this)):無法繼承原型鏈原型鏈繼承 Work.prototype = new Person():實例化的時候沒法給父類傳參;
在TS中定義類:
class Person {
name: string; // 屬性 前面省略了public關鍵字
constructor(n: string) { //實例化的時候觸發的方法
this.name = n;
};
run():void {
console.log(this.name)
}
}
const P = new Person('zhangsan')
P.run()
// 在TS中實現繼承(super,extends: 繼承)
class Person {
name: string;
constructor(name:string) {
this.name = name;
};
run():string {
console.log(this.name)
}
}
class Web extends Person {
constructor(name: string){
super(name);
}
}
const w = new Web('lisi')
w.run();
類裏面的修飾符:
1. public:共有;
2. protected:受保護類型,在類裏面,子類裏面可以訪問,在類外部無法訪問;
3. private:在類裏面可以訪問,在子類和類外部五方訪問
4. 屬性不加修飾符,默認是public屬性,表示共有屬性
TS如何定義靜態方法
class Person {
public name:string;
constructor(name:string) {
this.name = name;
}
run() {
console.log('asdfds')
}
static work() { //靜態沒辦法調用類裏面的方法和屬性
console.log('renshengyijingrucidejiannan')
}
}
// Person.work()// 調用靜態方法
多態:父類定義一個方法不去實現,讓繼承它的子類去實現,每一個子類有不同的表現抽象類,抽象方法使用關鍵字,抽象類的子類必須實現抽象類裏面的抽象方法。
abstract class Animal {
name:string;
constructor(name:any){
this.name = name;
}
abstract eat():any;
}
class Dog extends Animal {
constructor(name: any) {
super(name);
};
eat() {
console.log(this.name + '抽象方法繼承')
}
}
const dog = new Dog('小花花')
TS中的接口(interface):接口是一種規範的定義,可以規範屬性,函數,類等
1. 屬性接口,對json的約束
interface FullName {
firstName: string;
lastName: string;
age?:number; //可選屬性
}
function printName(name: FullName) {
return (name.firstName+'--'+name.lastName+'年齡:'+name.age)
}
const obj = {
firstName:'zhang',
lastName:'san',
age: 18
}
let str = printName(obj);
console.log(str)
2. 函數類型接口
interface encrypt {
(key:string, value:string):string;
}
const md5: encrypt = function(key:string,value: string):string {
return key+value;
}
console.log(md5('name','zhangsan'))
function createArray(length: number, value:any): Array<any> {
let result = [];
for (let i = 0; i < length; i++) {
result[i] = value++;
}
return result;
}
createArray(3, x); // ['x', 'x', 'x']
3. 可索引接口:針對數組,對象的約束(不常用)
4. 類--類型接口:對類的約束和抽象類有點相似(使用implements實現接口)類繼承接口
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 + '吃骨頭')
}
}
const d = new Dog('小黑')
d.eat()
5. 接口的擴展:接口可以繼承接口(切記只有類型可以實現接口(反之不行),接口可以通過extends繼承接口,接口不能繼承類!!!!)
interface Animal {
eat():void;
}
interface People extends Animal {// 這裏的人接口就繼承了Animal接口
work(): void;
}
class Programmer {
name: string;
constructor(name: string) {
this.name = name;
};
coding(code: string) {
console.log(this.name + code)
}
}
class Web extends Programmer implements People { //被當做類來處理
constructor(name: string) {
super(name) /**這裏繼承了類,必須要有super*/
};
eat(){
console.log(this.name + '喜歡吃肉')
};
work(){
console.log('前端工程師')
}
}
const W = new Web('zhanghu');
W.eat();
W.work();
W.coding('寫代碼')
泛型: 使用泛型來創建可重用的組件;要求傳入參數和返回的類型一致
示例
function identify<T>(arg: T): T {
return arg;
}
let output = identify<string>('人生就像一場戲');
console.log(output);
// 創建自定義泛型Array
function loggingIdentity<T>(arg: Array<T>):Array<T> {
console.log(arg.length);
return arg
}
let arr = loggingIdentity([1,2,3,4])
console.log(arr)
function identify<T>(arg:T):T{
return arg;
}
* 以下三種表達式同樣的效果喲
* 以下三種表達式同樣的效果喲
let myIdentify:<T>(arg: T) => T = identify;
let myIdentity: {<T>(arg: T): T} = identity;// 對象字面量來定義
let myIdentity: <U>(arg: U) => U = identity;
把上面的對象字面量來作爲一個接口
interface GenericIdentify {
<T>(arg: T): T;
}
function identify<T>(arg:T):T{
return arg;
}
let myIdentify: GenericIdentify = identify;
泛型接口
interface GenericIdentify<T> {
(arg: T): T; //說明接口裏面是一個函數
}
function identify<T>(arg: T): T {
return arg;
}
let myIdentify: GenericIdentify<string> =identify;
myIdentify('zhanghu')
泛型類
class Minclass {
public list: number[] = [7,77,88];
add(num: number) {
this.list.push(num);
};
min():number {
return Math.min(...this.list)
}
}
let m = new Minclass();
m.add(26);
m.add(46);
m.add(12);
m.add(8);
console.log(m.list)
console.log(m.min())
class Minclass<T> { //這裏聲明它是一個泛型類
public list: T[] = [];
add(value: T):void {
this.list.push(value);
};
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 Min = new Minclass<string>();//實例化類,並且制定了類的T代表的類型是number
// Min.add('123') //錯誤的寫法
Min.add('456');
Min.add('45');
Min.add('46');
Min.add('56');
console.log(Min.list);
console.log(Min.min())
泛型類當做參數
class User {
username: string | undefined;
password: string | undefined;
}
// class MysqDb{
// add(user: User): boolean {
// console.log(user);
// return true
// }
// }
class MysqDb<T>{ // 操作泛型類
add(user: T): boolean {
console.log(user);
return true
}
}
let U = new User();
U.username = 'zhanghu';
U.password = '123456';
let DB = new MysqDb<User>(); //把類當做是一個參數傳入泛型類裏面去
DB.add(U);
實例
功能:定義一個操作數據庫的庫,支持mysql、MongoDB
要求1:MySQL,MongoDB功能一樣,都有add, update, delete,get方法;
注意: 約束統一的規範,以及代碼的重用
解決方案: 需要約束規範要定義接口,需要重用的要用到泛型
a. 接口:在面向隊形的編程中,接口是一種規範的定義,他定義類行爲和動作的規範
b.泛型:通俗理解;泛型就是解決類 接口方法的賦值(即代碼重用)
interface DBI<T> { //規範一個接口
add(info: T): boolean;
update(info: T, id: number): boolean;
delete(id: number): boolean;
get(id: number): any[];
}
// 定義一個操作MySQL數據庫的類, 注意:要實現泛型類型接口,這個類也應該是一個泛型類
class MySqlDb<T> implements DBI<T> { //類繼承接口(受接口的約束),實現接口裏面約束的方法
add(info: T): boolean {
console.log(info);
return true;
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
let list = [
{
width: '1080px',
height: '960px'
},
{
width: '680px',
height: '420px'
}]
return list;
}
}
// 實現操作MongoDB數據庫的類,同上
class MongoDB<U> implements DBI<U> {
add(info: U): boolean {
throw new Error("Method not implemented.");
}
update(info: U, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
throw new Error("Method not implemented.");
}
}
// 操作數據表:給用戶表添加數據,定義一個
User類做數據映射
class User {
name: string | undefined;
password: string | undefined;
age?: number | undefined;
// job: string | undefined;
}
let U = new User();
U.name = 'zhanghu';
U.password = '123456';
U.age = 99;
let oMySql = new MySqlDb<User>(); //使用User類約束傳入數據的合法性
oMySql.add(U);
let data = oMySql.get(2);
console.log(data)
同理換成MongoDB也是一樣的用法
let oMongDB = new MongoDB<User>();即可
模塊:內部模塊,外部模塊,通過export暴露,import使用,搞清楚export 和export default的區別:一個模塊中只有一個export default,並且用使用import引入時不加{};一個模塊中有多個export,並且用使用import引入時要加{}
* 命名空間(namespace):內部模塊 主要用於組織代碼,避免命名衝突
* 模塊(modules):ts外部模塊的簡稱,側重代碼的複用,一個模塊可能會有多個命名空間;
TS中的裝飾器:就是一個方法,可以注入到類,方法,屬性參數來擴展類,屬性,方法,參數的功能;常見的裝飾器有:
類裝飾器。屬性裝飾器;
方法裝飾器;參數裝飾器裝飾器的寫法: 普通裝飾器(無法傳參),裝飾器工廠(可傳參)裝飾器是過去幾年中JS最大的成就之一,已經是es7的標準特性之一
1. 普通類裝飾器(沒有傳參)
function logClass(params: any) {
console.log(params);
// params 就是當前類,這時候就可以在這裏給類擴展屬性
params.prototype.apiUrl = '動態擴展屬性';
params.prototype.run = () => {
console.log('我是run方法')
}
}
@logClass
class HttpClient {
name: string;
constructor(name:string){
this.name = name;
}
getData() {}
}
const http: any = new HttpClient('zhanghu');
http.run()
2. 工廠裝飾器(有傳參)
function logClass(params: any) {
return function(target: any) {
console.log(target);
// console.log(params);
target.prototype.apiUrl = params;
}
}
@logClass('hello') // 傳入的參數('hello 工廠裝飾器')賦給了params; 類(HttpClient)賦給target
class HttpClient {
name: string;
constructor(name:string){
this.name = name;
}
getData() {}
}
const http:any = new HttpClient('zhjanghu');
console.log(http.apiUrl)
2. 屬性裝飾器
屬性裝飾器表達式會在運行是當作函數被調用,傳入下列兩個參數
a. 對於靜態成員來說是類的構造函數,對於實例成員是類的原型
a. 成員的名字
// 屬性裝飾器
function logProperty(params: any) {
return function(target: any, attr: any) {// 屬性裝飾器表達式會在運行是當作函數被調用,傳入下
列兩個參數1. 對於靜態成員來說是類的構造函數,對於實例成員是累的原型;2. 成員的名字
// console.log(target); //target代表的就是:類HttpClient
console.log(attr);
target[attr] = params //params的值爲:'這就是params'
}
}
class HttpClient {
@logProperty('這就是params')
name: string | undefined;
@logProperty('這是age')
age: number | undefined;
constructor(){}
getData() {
console.log(this.name);
console.log(this.age);
}
}
const http:any = new HttpClient();
http.getData();