typescript中爲了使編寫的程式碼更規範,更有利於維護,增加了型別校驗,在typescript中主要給我們提供了以下數據型別
ts 程式碼
必須指定型別
es5的正確寫法, ts中是錯誤寫法
var flag = true;
flag = 456;
typescript中爲了使編寫的程式碼更規範,更有利於維護,增加了型別校驗
var flag: boolean = true;
// flag = 123; // 錯誤
flag = false; // 正確
console.log(flag);
var num: number = 123;
num = 456;
console.log(num); // 正確
num = 'str'; // 錯誤
var str:string = 'this is ts';
str = 'haha'; // 正確
str = true; // 錯誤
ts中定義陣列有兩種方式 :
var arr: number[] = [11, 22, 33]
var arr: Array<number> = [11, 22, 33]
// var arr=['1','2']; // es5定義陣列
var arr: number[] = [11, 22, 33];
console.log(arr);
var arr: Array<number>=[11, 22, 33];
console.log(arr)
元組型別是屬於陣列的一種
// 正常陣列
var arr: Array<number> = [11, 22, 33];
console.log(arr)
// 元祖型別
let arr: [number, string] = [123, 'this is ts'];
console.log(arr);
隨着計算機的不斷普及,程式不僅只用於數值計算,還更廣泛地用於處理非數值的數據。
例如:性別、月份、星期幾、顏色、單位名、學歷 學曆、職業等,都不是數值數據。
在其它程式設計語言中,一般用一個數值來代表某一狀態,這種處理方法不直觀,易讀性差。
如果能在程式中用自然語言中有相應含義的單詞來代表某一狀態,則程式就很容易閱讀和理解。
也就是說,事先考慮到某一變數可能取的值,儘量用自然語言中含義清楚的單詞來表示它的每一個值,
這種方法稱爲列舉方法,用這種方法定義的型別稱列舉型別。
enum 列舉名{
識別符號[=整型常數],
識別符號[=整型常數],
...
識別符號[=整型常數],
} ;
enum Flag { success = 1, error = 2 };
let s: Flag = Flag.success;
console.log(s);
enum Color { blue , red, 'orange' };
var c: Color = Color.red;
console.log(c); // 1 如果識別符號沒有賦值 它的值就是下標
enum Color { blue, red = 3, 'orange' };
var c: Color = Color.red;
console.log(c); // 3
var c: Color = Color.orange;
console.log(c); // 4
enum Err { 'undefined' = -1, 'null' = -2, 'success' = 1 };
var e: Err = Err.success;
console.log(e);
var num: any = 123;
num = 'str';
num = true;
console.log(num)
// 任意型別的用處
var oBox: any = document.getElementById('box');
oBox.style.color = 'red';
null
和undefined
其他(never
型別)數據型別的子型別
var num: number;
console.log(num) // 輸出:undefined 報錯
var num: undefined;
console.log(num) // 輸出:undefined //正確
var num: number | undefined;
num = 123;
console.log(num);
// 定義沒有賦值就是undefined
var num: number | undefined;
console.log(num);
var num: null;
num = null;
//一個元素可能是 number型別 可能是null 可能是undefined
var num: number | null | undefined;
num = 1234;
console.log(num)
typescript
中的void
表示沒有任何型別,一般用於定義方法的時候方法沒有返回值。
表示方法沒有返回任何型別
// es5的定義方法
function run() {
console.log('run')
}
run();
// 正確寫法
function run(): void {
console.log('run')
}
run();
// 錯誤寫法
function run(): undefined {
console.log('run')
}
run();
// 正確寫法
function run(): number {
return 123;
}
run();
是其他型別 (包括
null
和undefined
)的子型別,代表從不會出現的值
。
// 這意味着宣告never的變數只能被never型別所賦值。
var a: undefined;
a = undefined;
var b: null;
b = null;
var a: never;
// a = 123; // 錯誤的寫法
a = (() => {
throw new Error('錯誤');
})()
es5定義函數的方法
// 函數宣告法
function run() {
return 'run';
}
// 函數表達式
var run2 = function() {
return 'run2';
}
ts中定義函數的方法
//函數宣告法
function run(): string {
return 'run';
}
//錯誤寫法
function run(): string {
return 123;
}
// 函數表達式
var fun2 = function(): number {
return 123;
}
fun2(); /* 呼叫方法 */
ts中定義方法傳參
function getInfo(name: string, age: number): string {
return `${name} --- ${age}`;
}
getInfo('zhangsan', 20);
var getInfo = function(name: string, age: number): string {
return `${name} --- ${age}`;
}
getInfo('zhangsan', 40);
沒有返回值的方法
function run(): void {
console.log('run')
}
run();
es5裏面方法的實參和行參可以不一樣,但是ts中必須一樣,如果不一樣就需要設定可選參數
注意: 可選參數必須設定到參數的最後面
// 正確寫法
function getInfo(name: string, age?: number): string {
if(age) {
return `${name} --- ${age}`;
}else{
return `${name} ---年齡保密`;
}
}
getInfo('zhangsan');
getInfo('zhangsan',123);
// 錯誤寫法
function getInfo(name?: string, age: number): string {
if(age) {
return `${name} --- ${age}`;
}else{
return `${name} ---年齡保密`;
}
}
getInfo('zhangsan')
es5 裏面沒法設定預設參數,es6 和 ts 中都可以設定預設參數
function getInfo(name: string, age: number = 20): string {
if(age) {
return `${name} --- ${age}`;
}else{
return `${name} ---年齡保密`;
}
}
getInfo('張三');
getInfo('張三',30);
function sum(a: number, b: number, c: number, d: number): number {
return a + b + c + d;
}
sum(1,2,3,4);
三點運算子 接受新參傳過來的值
function sum(...result: number[]): number {
var sum = 0;
for(var i = 0;i < result.length; i++){
sum += result[i];
}
return sum;
}
sum(1, 2, 3, 4, 5, 6);
function sum(a: number, b: number, ...result: number[]): number {
var sum = a + b;
for(var i = 0;i< result.length; i++){
sum += result[i];
}
return sum;
}
sum(1, 2, 3, 4, 5, 6);
java中方法的過載:過載指的是兩個或者兩個以上同名函數,但它們的參數不一樣,這時會出現函數過載的情況。
typescript中的過載:通過爲同一個函數提供多個函數型別定義來試下多種功能的目的。
ts爲了相容es5 以及 es6 過載的寫法和java中有區別。
es5中出現同名方法,下面 下麪的會替換上面的方法
// es5方法覆蓋
function css(config) {
}
function css(config, value) {
}
ts中的過載
function getInfo(name: string): string;
function getInfo(age: number): string;
function getInfo(str: any): any {
if(typeof str === 'string') {
return '我叫:' + str;
}else{
return '我的年齡是' + str;
}
}
getInfo('張三'); // 正確
getInfo(20); // 正確
getInfo(true); // 錯誤寫法
function getInfo(name: string): string;
function getInfo(name: string, age: number): string;
function getInfo(name: any,age?: any): any {
if(age) {
return '我叫:'+ name + '我的年齡是' + age;
} else {
return '我叫:' + name;
}
}
getInfo('zhangsan'); // 正確
getInfo(123); // 錯誤
getInfo('zhangsan', 20); //
this
指向的問題 箭頭函數裏面的this指向上下文
setTimeout(function() {
console.log('run')
}, 1000)
setTimeout(() => {
console.log('run')
}, 1000)
// es5
function Person(name){
this.name = name;
this.run = function() {
console.log(this.name)
}
}
var p = new Person('張三');
p.run()
// ts中定義類
class Person{
name: string; //屬性 前面省略了public關鍵詞
constructor(n: string){ //建構函式 範例化類的時候觸發的方法
this.name = n;
}
run(): void {
alert(this.name);
}
}
var p = new Person('張三');
p.run()
class Person{
name: string;
constructor(name: string) { //建構函式 範例化類的時候觸發的方法
this.name = name;
}
getName(): string{
return this.name;
}
setName(name: string): void {
this.name = name;
}
}
var p = new Person('張三');
p.getName();
p.setName('李四');
p.getName();
class Person{
name: string;
constructor(name: string){
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
var p=new Person('王五');
p.run();
class Web extends Person{
constructor(name:string){
super(name); /*初始化父類別的建構函式*/
}
}
var w=new Web('李四');
w.run();
ts中繼承的探討 父類別的方法和子類的方法一致
class Person{
name: string;
constructor(name: string){
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
var p = new Person('王五');
p.run()
class Web extends Person{
constructor(name: string){
super(name); /*初始化父類別的建構函式*/
}
run(): string {
return `${this.name}在運動-子類`
}
work() {
alert(`${this.name}在工作`)
}
}
var w=new Web('李四');
w.work();
w.run();
typescript裏面定義屬性的時候給我們提供了 三種修飾符:
public
:公有 在當前類裏面、 子類 、類外面都可以存取
protected
:保護型別 在當前類裏面、子類裏面可以存取 ,在類外部沒法存取
private
:私有 在當前類裏面可以存取,子類、類外部都沒法存取
屬性如果不加修飾符 預設就是 公有 (public)
public
class Person{
public name:string; /*公有屬性*/
constructor(name:string){
this.name=name;
}
run():string{
return `${this.name}在運動`
}
}
var p=new Person('王五');
p.run()
class Web extends Person{
constructor(name:s tring) {
super(name); /*初始化父類別的建構函式*/
}
run(): string {
return `${this.name}在運動-子類`
}
work() {
alert(`${this.name}在工作`)
}
}
var w = new Web('李四');
w.work();
類外部存取公有屬性
class Person{
public name: string; /*公有屬性*/
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
var p = new Person('哈哈哈');
p.name;
protected
class Person{
protected name: string; /*公有屬性*/
constructor(name: string) {
this.name=name;
}
run():string{
return `${this.name}在運動`
}
}
var p=new Person('王五');
p.run()
class Web extends Person{
constructor(name: string) {
super(name); /*初始化父類別的建構函式*/
}
work(){
alert(`${this.name}在工作`)
}
}
var w = new Web('李四11');
w.work();
w.run();
類外外部沒法存取保護型別的屬性
class Person{
protected name: string; /* 保護型別 */
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
var p = new Person('哈哈哈');
alert(p.name);
private
class Person{
private name: string; /*私有*/
constructor(name: string) {
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
class Web extends Person{
constructor(name: string){
super(name)
}
work(){
console.log(`${this.name}在工作`)
}
}
class Person{
private name: string; /*私有*/
constructor(name: string){
this.name = name;
}
run(): string {
return `${this.name}在運動`
}
}
var p = new Person('哈哈哈');
p.run();
function Person() {
this.run1 = function() {
}
}
Person.name = '哈哈哈';
Person.run2 = function() { // 靜態方法
}
var p = new Person();
Person.run2(); // 靜態方法的呼叫
jquery
舉例
function $(element) {
return new Base(element)
}
$.get=function() {
}
function Base(element) {
this.element = `獲取dom節點`;
this.css=function(arr, value){
this.element.style.arr = value;
}
}
$('#box').css('color', 'red')
$.get('url', function() {})
靜態屬性
class Per{
public name: string;
public age: number = 20;
//靜態屬性
static sex = "男";
constructor(name: string) {
this.name = name;
}
run() { /*實體方法*/
alert(`${this.name}在運動`)
}
work() {
alert(`${this.name}在工作`)
}
static print() { /*靜態方法 裏面沒法直接呼叫類裏面的屬性*/
alert('print方法'+Per.sex);
}
}
var p=new Per('張三');
p.run();
Per.print();
Per.sex;
多型: 父類別定義一個方法不去實現,讓繼承它的子類去實現 每一個子類有不同的表現
//多型屬於繼承
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 + '吃糧食'
}
}
class Cat extends Animal{
constructor(name: string){
super(name)
}
eat() {
return this.name + '吃老鼠'
}
}
typescript中的抽象類:它是提供其他類繼承的基礎類別,不能直接被範例化。
用abstract
關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現並且必須在派生類中實現
abstract
抽象方法只能放在抽象類裏面
抽象類和抽象方法用來定義標準 。 標準:Animal 這個類要求它的子類必須包含eat方法
abstract class Animal{
public name: string;
constructor(name: string) {
this.name = name;
}
abstract eat(): any; // 抽象方法不包含具體實現並且必須在派生類中實現。
run(){
console.log('其他方法可以不實現')
}
}
// var a = new Animal() /*錯誤的寫法, 不能範例化*/
class Dog extends Animal{
// 抽象類的子類必須實現抽象類裏面的抽象方法
constructor(name: any){
super(name)
}
eat(){
console.log(this.name + '吃糧食')
}
}
var d = new Dog('小花花');
d.eat();
class Cat extends Animal{
//抽象類的子類必須實現抽象類裏面的抽象方法
constructor(name:any){
super(name)
}
run(){
}
eat(){
console.log(this.name+'吃老鼠')
}
}
var c = new Cat('小花貓');
c.eat();
介面的作用:在物件導向的程式設計中,介面是一種規範的定義,它定義了行爲和動作的規範,在程式設計裏面,介面起到一種限制和規範的作用。介面定義了某一批類所需要遵守的規範,介面不關心這些類的內部狀態數據,也不關心這些類裡方法的實現細節,它只規定這批類裡必須提供某些方法,提供這些方法的類就可以滿足實際需要。 typescrip中的介面類似於java,同時還增加了更靈活的介面型別,包括屬性、函數、可索引和類等。
屬性介面: 對json的約束
ts中定義方法
function printLabel(): void {
console.log('printLabel');
}
printLabel();
ts 中定義方法傳入參數
function printLabel(label: string): void {
console.log('printLabel');
}
printLabel('hahah');
ts 中自定義方法傳入參數, 對json進行約束
function printLabel(labelInfo: { label: string }): void {
console.log('printLabel');
}
printLabel('hahah'); //錯誤寫法
printLabel({ name: '張三' }); //錯誤的寫法
printLabel({ label: '張三' }); //正確的寫法
介面:行爲和動作的規範,對批次方法進行約束
對批次方法傳入參數進行約束。
// 就是傳入物件的約束 屬性介面
interface FullName{
firstName:string; //注意;結束
secondName:string;
}
function printName(name: FullName) {
// 必須傳入物件 firstName secondName
console.log(name.firstName + '--' + name.secondName);
}
// printName('1213'); //錯誤
var obj = { /*傳入的參數必須包含 firstName secondName*/
age: 20,
firstName: '張',
secondName: '三'
};
printName(obj)
interface FullName{
firstName:string; //注意;結束
secondName:string;
}
function printName(name: FullName) {
// 必須傳入物件 firstName secondName
console.log(name.firstName + '--' + name.secondName);
}
function printInfo(info: FullName) {
// 必須傳入物件 firstName secondName
console.log(info.firstName + info.secondName);
}
var obj = { /*傳入的參數必須包含 firstName secondName*/
age: 20,
firstName: '張',
secondName: '三'
};
printName(obj);
printInfo({
firstName: '李',
secondName: '四'
})
可選屬性
interface FullName{
firstName: string;
secondName: string;
}
function getName(name: FullName) {
console.log(name)
}
// 參數的順序可以不一樣
getName({
secondName: 'secondName',
firstName: 'firstName'
})
interface FullName{
firstName: string;
secondName?: string;
}
function getName(name: FullName) {
console.log(name)
}
getName({
firstName:'firstName'
})
簡單封裝舉例, 原生js封裝的ajax
interface Config{
type: string;
url: string;
data?: string;
dataType: string;
}
// 簡單封裝舉例, 原生js封裝的ajax
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('chengong');
if(config.dataType == 'json') {
console.log(JSON.parse(xhr.responseText));
} else {
console.log(xhr.responseText)
}
}
}
}
ajax({
type: 'get',
data: 'name=zhangsan',
url: 'http://baidu.com/api/productlist', //api
dataType: 'json'
})
函數型別介面: 對方法傳入的參數 以及返回值進行約束 批次約束
加密的函數型別介面
interface encrypt{
(key: string, value: string): string;
}
var md5: encrypt = function(key: string, value :string): string{
//模擬操作
return key + value;
}
console.log(md5('name', 'zhangsan'));
var sha1: encrypt = function(key: string, value: string): string {
//模擬操作
return key + '----' + value;
}
console.log(sha1('name', 'lisi'));
可索引介面:陣列、物件的約束 (不常用)
// ts定義陣列的方式
var arr: number[] = [ 2342, 235325 ]
var arr1: Array<string> = ['111', '222']
//可索引介面 對陣列的約束
interface UserArr{
[index: number]: string
}
// var arr: UserArr=['aaa', 'bbb'];
// console.log(arr[0]);
var arr: UserArr = [123, 'bbb']; /*錯誤*/
console.log(arr[0]);
可索引介面 對物件的約束
interface UserObj{
[index:string]:string
}
var arr:UserObj={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 d = new Dog('小黑');
d.eat();
class Cat implements Animal{
name: string;
constructor(name: string){
this.name = name;
}
eat(food: string){
console.log(this.name + '吃' + food);
}
}
var c = new Cat('小花');
c.eat('老鼠');
介面擴充套件:介面可以繼承介面
interface Animal{
eat(): void;
}
interface Person extends Animal{
work(): void;
}
class Web implements Person{
public name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log(this.name + '喜歡吃饅頭')
}
work() {
console.log(this.name + '寫程式碼');
}
}
var w = new Web('小李');
w.eat();
interface Animal{
eat(): void;
}
interface Person extends Animal{
work(): void;
}
class Programmer{
public name: string;
constructor(name: string) {
this.name = name;
}
coding(code: string) {
console.log(this.name + code)
}
}
class Web extends Programmer implements Person{
constructor(name: string) {
super(name)
}
eat() {
console.log(this.name + '喜歡吃饅頭')
}
work() {
console.log(this.name + '寫程式碼');
}
}
var w = new Web('小李');
w.eat();
w.coding('寫ts程式碼');
泛型:軟體工程中,我們不僅要建立一致的定義良好的API,同時也要考慮可重用性。 元件不僅能夠支援當前的數據型別,同時也能支援未來的數據型別,這在建立大型系統時爲你提供了十分靈活的功能。
在像C#和Java這樣的語言中,可以使用泛型來建立可重用的元件,一個元件可以支援多種型別的數據。 這樣使用者就可以以自己的數據型別來使用元件。
通俗理解:泛型就是解決 類 介面 方法的複用性、以及對不特定數據型別的支援(型別校驗)
只能返回string型別的數據
function getData(value: string): string {
return value;
}
同時返回 string型別 和number型別 (程式碼冗餘)
function getData1(value: string): string {
return value;
}
function getData2(value: number): number {
return value;
}
同時返回 string型別 和number型別 any可以解決這個問題
function getData(value: any): any {
return '哈哈哈';
}
getData(123);
getData('str');
any放棄了型別檢查,傳入什麼 返回什麼。比如:傳入number 型別必須返回number型別 傳入 string型別必須返回string型別
傳入的參數型別和返回的參數型別可以不一致
function getData(value: any): any {
return '哈哈哈';
}
泛型:可以支援不特定的數據型別 要求:傳入的參數和返回的參數一直
T表示泛型,具體什麼型別是呼叫這個方法的時候決定的
function getData<T>(value: T): T {
return value;
}
getData<number>(123);
getData<string>('1214231');
getData<number>('2112'); /*錯誤的寫法*/
function getData<T>(value:T):any{
return '2145214214';
}
getData<number>(123); //參數必須是number
getData<string>('這是一個泛型');
泛型類:比如有個最小堆演算法,需要同時支援返回數位和字串 a - z兩種型別。 通過類的泛型來實現
class MinClass{
public list:number[] = [];
add(num: number) {
this.list.push(num)
}
min(): number {
var minNum = this.list[0];
for(var i = 0;i< this.list.length; i++){
if(minNum > this.list[i]){
minNum = this.list[i];
}
}
return minNum;
}
}
var m = new MinClass();
m.add(3);
m.add(22);
m.add(23);
m.add(6);
m.add(7);
m.min());
類的泛型
class MinClas<T>{
public list: T[] = [];
add(value: T): void {
this.list.push(value);
}
min(): T {
var minNum = this.list[0];
for(var i = 0;i < this.list.length; i++){
if(minNum > this.list[i]){
minNum = this.list[i];
}
}
return minNum;
}
}
var m1 = new MinClas<number>(); /* 範例化類 並且制定了類的T代表的型別是number */
m1.add(11);
m1.add(3);
m1.add(2);
m1.min();
var m2=new MinClas<string>(); /* 範例化類 並且制定了類的T代表的型別是string */
m2.add('c');
m2.add('a');
m2.add('v');
m2.min()
函數型別介面
interface ConfigFn{
(value1: string, value2: string): string;
}
var setData: ConfigFn = function(value1: string, value2: string): string {
return value1 + value2;
}
setData('name', '張三');
泛型介面
interface ConfigFn{
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
getData<string>('張三');
getData<string>(1243); //錯誤
泛型介面
interface ConfigFn<T>{
(value: T): T;
}
function getData<T>(value: T): T {
return value;
}
var myGetData: ConfigFn<string> = getData;
myGetData('20'); /*正確*/
myGetData(20) //錯誤
泛類:泛型可以幫助我們避免重複的程式碼以及對不特定數據型別的支援(型別校驗),下面 下麪我們看看把類當做參數的泛型類
1、定義個類
2、把類作爲參數來約束數據傳入的型別
// 比如有個最小堆演算法 普通型別
class MinClass{
public list: number[] = [];
add(num: number) {
this.list.push(num)
}
min(): number {
var minNum = this.list[0];
for(var i = 0;i< this.list.length; i++){
if(minNum > this.list[i]){
minNum = this.list[i];
}
}
return minNum;
}
}
var m1 = new MinClass();
m1.add(11);
m1.add(3);
m1.add(2);
m1.min()
類的泛型
class MinClas<T>{
public list: T[] = [];
add(value: T): void {
this.list.push(value);
}
min(): T {
var minNum = this.list[0];
for(var i = 0;i< this.list.length; i++){
if(minNum > this.list[i]){
minNum = this.list[i];
}
}
return minNum;
}
}
var m1 = new MinClas<number>(); //範例化類 並且指定了類的T代表的型別是number
m1.add(11);
m1.add(3);
m1.add(2);
m1.min()
var m2=new MinClas<string>(); //範例化類 並指定定了類的T代表的型別是string
m2.add('c');
m2.add('a');
m2.add('v');
m2.min()
定義一個User的類這個類的作用就是對映數據庫欄位
然後定義一個 MysqlDb的類這個類用於操作數據庫
然後把User類作爲參數傳入到MysqlDb中
var user=new User({
username:'張三',
password:'123456'
})
var Db=new MysqlDb();
Db.add(user);
把類作爲參數來約束數據傳入的型別
class User{
username:string | undefined;
pasword:string | undefined;
}
class MysqlDb{
add(user:User):boolean{
console.log(user);
return true;
}
}
var u = new User();
u.username = '張三';
u.pasword = '123456';
var Db = new MysqlDb();
Db.add(u);
class ArticleCate{
title: string | undefined;
desc: string | undefined;
status: number | undefined
}
class MysqlDb{
add(info: ArticleCate): boolean{
console.log(info);
console.log(info.title);
return true;
}
}
var a = new ArticleCate();
a.title = "國內";
a.desc = "國內新聞";
a.status = 1;
var Db = new MysqlDb();
Db.add(a);
//定義操作數據庫的泛型類
class MysqlDb<T>{
add(info: T): boolean {
console.log(info);
return true;
}
updated(info: T, id: number): boolean {
console.log(info);
console.log(id);
return true;
}
}
// 想給User表增加數據
// 1、定義一個User類 和數據庫進行對映
class User{
username: string | undefined;
pasword: string | undefined;
}
var u = new User();
u.username = '張三';
u.pasword = '123456';
var Db = new MysqlDb<User>();
Db.add(u);
// 2、相關ArticleCate增加數據 定義一個ArticleCate類 和數據庫進行對映
class ArticleCate{
title: string | undefined;
desc: string | undefined;
status: number | undefined;
constructor(params: {
title: string | undefined,
desc: string | undefined,
status?: number | undefined
}){
this.title = params.title;
this.desc = params.desc;
this.status = params.status;
}
}
// 增加操作
var a = new ArticleCate({
title: '分類',
desc: '1111',
status: 1
});
// 類當做參數的泛型類
var Db = new MysqlDb<ArticleCate>();
Db.add(a);
//修改數據
var a = new ArticleCate({
title: '分類111',
desc: '2222'
});
a.status = 0;
var Db = new MysqlDb<ArticleCate>();
Db.updated(a, 12);
案例展示 :
功能:定義一個操作數據庫的庫 支援 Mysql Mssql MongoDb
要求1:Mysql MsSql MongoDb功能一樣 都有 add update delete get方法
注意:約束統一的規範、以及程式碼重用
解決方案:需要約束規範所以要定義介面 ,需要程式碼重用所以用到泛型
1、介面:在物件導向的程式設計中,介面是一種規範的定義,它定義了行爲和動作的規範
2、泛型 通俗理解:泛型就是解決 類 介面 方法的複用性、
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>{
constructor(){
console.log('數據庫建立連線');
}
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[] {
var list = [
{
title:'xxxx',
desc:'xxxxxxxxxx'
},
{
title:'xxxx',
desc:'xxxxxxxxxx'
}
]
return list;
}
}
定義一個操作mssql數據庫的類
class MsSqlDb<T> implements DBI<T>{
constructor(){
console.log('數據庫建立連線');
}
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[] {
var list=[
{
title:'xxxx',
desc:'xxxxxxxxxx'
},
{
title:'xxxx',
desc:'xxxxxxxxxx'
}
]
return list;
}
}
操作使用者表 定義一個User類和數據表做對映
class User{
username: string | undefined;
password: string | undefined;
}
var u = new User();
u.username = '張三111';
u.password = '123456';
var oMysql = new MysqlDb<User>(); //類作爲參數來約束數據傳入的型別
oMysql.add(u);
class User{
username: string | undefined;
password: string | undefined;
}
var u = new User();
u.username = '張三2222';
u.password = '123456';
var oMssql = new MsSqlDb<User>();
oMssql.add(u);
//獲取User表 ID=4的數據
var data = oMssql.get(4);
console.log(data);
在程式碼量較大的情況下,爲了避免各種變數命名相沖突,可將相似功能的函數、類、介面等放置到名稱空間內
同Java的包、.Net的名稱空間一樣,TypeScript的名稱空間可以將程式碼包裹起來,只對外暴露需要在外部存取的物件。名稱空間內的物件通過export關鍵字對外暴露。
名稱空間和模組的區別:
名稱空間:內部模組,主要用於組織程式碼,避免命名衝突。
模 塊:ts的外部模組的簡稱,側重程式碼的複用,一個模組裡可能會有多個名稱空間。
// modules/animal.ts
export namespace A{
interface Animal {
name: string;
eat(): void;
}
export class Dog implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 在吃狗糧。`);
}
}
export class Cat implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 吃貓糧。`);
}
}
}
export namespace B{
interface Animal {
name: string;
eat(): void;
}
export class Dog implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 在吃狗糧。`);
}
}
export class Cat implements Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name} 在吃貓糧。`);
}
}
}
名稱空間和模組的區別:
名稱空間:內部模組,主要用於組織程式碼,避免命名衝突。
模 塊:ts的外部模組的簡稱,側重程式碼的複用,一個模組裡可能會有多個名稱空間。
import { A, B } from './modules/animal';
var d = new A.Dog('小黑');
d.eat();
var dog = new B.Dog('小花');
dog.eat();
裝飾器:裝飾器是一種特殊型別的宣告,它能夠被附加到類宣告,方法,屬性或參數上,可以修改類的行爲。
通俗的講裝飾器就是一個方法,可以注入到類、方法、屬性參數上來擴充套件類、屬性、方法、參數的功能。
常見的裝飾器有:類裝飾器、屬性裝飾器、方法裝飾器、參數裝飾器
裝飾器的寫法:普通裝飾器(無法傳參) 、 裝飾器工廠(可傳參)
裝飾器是過去幾年中js最大的成就之一,已是Es7的標準特性之一
類裝飾器:類裝飾器在類宣告之前被宣告(緊靠着類宣告)。 類裝飾器應用於類建構函式,可以用來監視,修改或替換類定義。 傳入一個參數
function logClass(params: any) {
console.log(params);
// params 就是當前類
params.prototype.apiUrl = '動態擴充套件的屬性';
params.prototype.run = function() {
console.log('我是一個run方法');
}
}
@logClass
class HttpClient{
constructor(){
}
getData(){
}
}
var http:any=new HttpClient();
console.log(http.apiUrl);
http.run();
function logClass(params: string) {
return function(target: any) {
console.log(target);
console.log(params);
target.prototype.apiUrl = params;
}
}
@logClass('http://www.itying.com/api')
class HttpClient{
constructor() {
}
getData(){
}
}
var http:any=new HttpClient();
console.log(http.apiUrl);
下面 下麪是一個過載建構函式的例子。
類裝飾器表達式會在執行時當作函數被呼叫,類別建構函式作爲其唯一的參數。
如果類裝飾器返回一個值,它會使用提供的建構函式來替換類的宣告。
function logClass(target:any){
console.log(target);
return class extends target{
apiUrl:any='我是修改後的數據';
getData(){
this.apiUrl=this.apiUrl+'----';
console.log(this.apiUrl);
}
}
}
@logClass
class HttpClient{
public apiUrl:string | undefined;
constructor(){
this.apiUrl='我是建構函式裏面的apiUrl';
}
getData(){
console.log(this.apiUrl);
}
}
var http=new HttpClient();
http.getData();
屬性裝飾器表達式會在執行時當作函數被呼叫,傳入下列2個參數:
1、對於靜態成員來說是類別建構函式,對於範例成員是類的原型物件。
2、成員的名字。
//類裝飾器
function logClass(params:string){
return function(target:any){
// console.log(target);
// console.log(params);
}
}
//屬性裝飾器
function logProperty(params:any){
return function(target:any,attr:any){
console.log(target);
console.log(attr);
target[attr]=params;
}
}
@logClass('xxxx')
class HttpClient{
@logProperty('http://itying.com')
public url:any |undefined;
constructor(){
}
getData(){
console.log(this.url);
}
}
var http=new HttpClient();
http.getData();
它會被應用到方法的 屬性描述符上,可以用來監視,修改或者替換方法定義。
方法裝飾會在執行時傳入下列3個參數:
1、對於靜態成員來說是類別建構函式,對於範例成員是類的原型物件。
2、成員的名字。
3、成員的屬性描述符。
// 方法裝飾器一
function get(params: any){
return function(target: any, methodName: any,desc: any){
console.log(target);
console.log(methodName);
console.log(desc);
target.apiUrl = 'xxxx';
target.run = function(){
console.log('run');
}
}
}
class HttpClient{
public url: any |undefined;
constructor() {
}
@get('http://www.itying,com')
getData() {
console.log(this.url);
}
}
var 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.value);
//修改裝飾器的方法 把裝飾器方法裏面傳入的所有參數改爲string型別
//1、儲存當前的方法
var oMethod = desc.value;
desc.value = function(...args: any[]){
args = args.map((value) => {
return String(value);
})
oMethod.apply(this, args);
}
}
}
class HttpClient{
public url: any | undefined;
constructor() {
}
@get('http://www.itying,com')
getData(...args: any[]) {
console.log(args);
console.log('我是getData裏面的方法');
}
}
var http = new HttpClient();
http.getData(123, 'xxx');
參數裝飾器表達式會在執行時當作函數被呼叫,傳入下列3個參數:
1、對於靜態成員來說是類別建構函式,對於範例成員是類的原型物件。
2、參數的名字。
3、參數在函數參數列表中的索引。
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('xxxxx') uuid: any){
console.log(uuid);
}
}
var http:any = new HttpClient();
http.getData(123456);
console.log( http.apiUrl);
裝飾器執行順序
屬性》方法》方法參數》類
如果有多個同樣的裝飾器,它會先執行後面的
function logClass1(params: string) {
return function(target: any) {
console.log('類裝飾器1')
}
}
function logClass2(params: string) {
return function(target: any) {
console.log('類裝飾器2')
}
}
function logAttribute1(params?: string) {
return function(target: any, attrName: any) {
console.log('屬性裝飾器1')
}
}
function logAttribute2(params?: string) {
return function(target: any, attrName: any) {
console.log('屬性裝飾器2')
}
}
function logMethod1(params?: string) {
return function(target: any, attrName: any, desc: any) {
console.log('方法裝飾器1')
}
}
function logMethod2(params?: string) {
return function(target: any, attrName: any, desc: any) {
console.log('方法裝飾器2')
}
}
function logParams1(params?: string) {
return function(target: any, attrName: any, desc: any) {
console.log('方法參數裝飾器1')
}
}
function logParams2(params?: string) {
return function(target: any, attrName: any, desc: any) {
console.log('方法參數裝飾器2')
}
}
@logClass1('http://www.itying.com/api')
@logClass2('xxxx')
class HttpClient{
@logAttribute1()
@logAttribute2()
public apiUrl: string | undefined;
constructor() {
}
@logMethod1()
@logMethod2()
getData() {
return true;
}
setData(@logParams1() attr1: any, @logParams2() attr2: any,) {
}
}
var http:any=new HttpClient();