TypeScript
1.微软开发的开源的汇编语言
示列
function greeter(ts :string) {
return "hellow"+ts;
}
var test = "a";
let user = "Jane User";
document.body.innerHTML = greeter(user);
:string 表示的是类型注解
接口
interface person{
lastName:String;
firstName:String;
}
function greeter(person:person) {
return "hello"+person.firstName+" "+person.lastName;
}
let user = { firstName:"Jane",lastName:"User"}
document.body.innerHTML = greeter(user);
类
class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
interface Person {
firstName: string;
lastName: string;
}
function greeter(person: Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
TypeScript基本数据类型
-
布尔值
let isDone: boolean = false;
-
数字
let decLiteral: number = 6; let hexLiteral: number = 0xf00d; let binaryLiteral: number = 0b1010; let octalLiteral: number = 0o744;
-
字符串 模板字符串 ${}
let name: string = "bob"; name = "smith";
-
数组
let list: number[] = [1, 2, 3];
-
元祖 Tuple
元祖相当于混个多种类型
// Declare a tuple type let x: [string, number]; // Initialize it x = ['hello', 10]; // OK // Initialize it incorrectly x = [10, 'hello']; // Error
-
枚举
-
任意值
对于一些现在还不算清楚的变量指定一个类型我们会采取任意类型
let notSure: any = 4; notSure = "maybe a string instead"; notSure = false; // okay, definitely a boolean
-
空值
-
Null和Undefined
是所有类型的子类型
-
Never
表示那些永不存在的值的类型
-
Object
代表的是非原始类型,也就是除了
number
,string
,boolean
,symbol
,null
或undefined
之外的类型。
使用方法
- tsc --init
ES5定义函数的方法
//普通函数的申明
function run() {
return "run"
}
//匿名函数声明
var run2 = function() {
return "run"
}
ts中定义函数的方法
如果有返回值
//函数声明需要返回声明
function run():string{
return "run";
}
//匿名函数法
var fun2 = function():number{
return 123;
}
//ts中定义方法传参
函数声明
function getInfo(name:string.age:number):string{
return `${name} ----- ${age}`;
}
匿名函数
var getInfo = function(name:string.age:number):string{
return `${name} ----- ${age}`;
}
//没有返回值的方法
function run():void{
return "age";
}
方法可选参数
function run(name:string,age?:number){
if(age){
return `${age}`;
}else{
return `${name}`;
}
}
?的意思是可选参数相当于可以传入参数也可以不传入参数
//可选参数必须到参数的最后面
默认参数
es5里面没法设置默认参数。es6和ts可以设置
function run(name:string,age:number =20){
if(age){
return `${age}`;
}else{
return `${name}`;
}
}
剩余参数
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);
函数重载
首先如果是es5出现同名的方法,下面的会替代上面的方法
function css (config){
}
function css (config,value){
}
//ts中的重载
function getInfo(name:string):string;
function getInfo(age:string):number;
function getInfo(str:any):any{
if(typeof str ==='string'){
return '我叫'+str
}else {
return '我的年龄'+str;
}
}
箭头函数
setTimeout(()=>{
console.log("我要做一些事情了")
},1000)
//箭头函数this指向上下文
es5创建对象和继承
1.es5里面的类
最简单的类
function Person(){
this.name="1";
this.age=1;
}
var p = new Person();
alert(p.name);
2.构造函数和原型链里面增加的方法
function Person(){
this.name="1";
this.age=1;
this.run = function(){
console.log(this.name+"运动");
}
}
Person.prptotype.sex="男";
Person.prptotype.work=function(){
}
var p = new Person();
p.work();
原型链上面的属性会被多个实例分享 构造函数并不会这样
3类里面的静态方法
function Person(){
this.name="1";
this.age=1;
this.run = function(){
console.log(this.name+"运动");
}
}
Person.prototype.sex="男";
Person.prototype.work=function(){
}
var p = new Person();
p.work()
Person.run = function(){
console.log("你好啊");
}
Person.run();
原型链上面的属性会被多个实例分享 构造函数并不会这样
4.es5的继承
原型链+对象冒充的组合继承模式
对象冒充
function Person(){
this.name="1";
this.age=1;
this.run = function(){
console.log(this.name+"运动");
}
}
//对象冒充实现继承
function Web(){
Person.call(this)
}
var w = new Web();
w.run();//对象冒充可以继承构造函数的属性和方法
//对象冒充没有办法进行原型链的方法
使用原型链实现继承
function Person(){
this.name="1";
this.age=1;
this.run = function(){
console.log(this.name+"运动");
}
}
function web(){
}
web.prototype = new Person();
//使用原型链的方法实现继承
var w = new web();
w.run();
缺点:实例化子类没有办法给父类进行传参
原型链+构造函数的组合构造模式
function Person(name,age){
this.name=name;
this.age=age;
this.run = function(){
console.log(this.name+"运动");
}
}
function web(name,age){
Person.call(this.name,this.age)
}
对象冒充实例化子类可以给父类传参
原型链+对象冒充的二种方法
web.prototype = person.prototype
ts中如何定义一个类
class Person{
name:string; //属性 前面省去了public
constructor(n:string){
//构造函数 实例化的时候触发的方法
this.name = n;
}
run():void{
alert(this.name);
}
}
var p = new Person('张三');
p.run();
ts中如何实现继承
extends super
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("lisi");
类里面有三种修饰符
public 表示公有 类 子类 类外部都是可以访问 默认为public类型
protected 保护类型 在类里面,子类里面可以访问,在类外部是不能访问的
private 私有化 类里面可以访问,其他都不能够访问
静态方法
function Person(){
this.run1 = function(){
}
}
Person.name="哈哈哈"
Person.run()=function(){
}
var p = new Person();
class Person{
private name:string;
constructor(name:string){
this.name=name;
}
run(){
alert(`${this.name}在运动`);
}
work(){
alert(`${this.name}在工作`)
}
//静态方法
static print(){
alert('print')
}
}
Person.print();
静态方法没有办法直接调用 属性
抽象类
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(){
console.log(this.name+"吃粮食");
}
}
var d = new Dog('asas');
d.eat();
多态
父类定义一个方法不去实现,让继承它的子类去实现,每个子类有不同的表现
多态属于继承
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+"吃老鼠";
}
}
接口的概念以及属性类型接口
接口的作用,在面向对象的编程中,接口是一种规范的定义,他定义了行为和动作的规范,在程序设计里面,接口起限制个规范的作用。接口定义了某一批类所需要遵循的规范,接口没有必要关系这些类的内部状态和数据,也不关心类里面方法实现的细节。他只是规定了这批类里面需要提供某些方法,提供这些方法的类可以满足实际需要。类似于java,但是也是在里面增加了一些其他的东西属性、函数、索引类型
// ts定义方法传参数
// function printLabel(label:string):void{
// console.log("print");
// }
//ts自定义方法对json进行约束
function printLabel(labelInfo:{label:string}):void{
console.log("print");
}
printLabel({label:"张三"});
//对批量方法传入参数进行约束
//接口:行为和动作规范:对批量方法进行约束
interface fullName{
firstName:string; //注意;结束
secondName:string;
}
function printName(name:fullName):void{
//必须传入对象 firstName secondName
console.log(name.firstName);
}
var obj = {
firstName:'张三',
secondName:'sa',
}
printName(obj);
输出结果:张三
interface fullName{
firstName:String;
secondName:string;
age:number;
}
function printInfo(name:fullName){
console.log(name.firstName+name.secondName)
}
function printAge(info:fullName){
console.log(info.age);
}
var obj ={
age:20,
firstName:"ma",
secondName:"haitao",
}
printAge(obj);
输出结果:20
接口可选属性
ajax封装
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("成功")
if(config.dataType=='json'){
JSON.parse(xhr.responseText);
}else{
console.log(xhr.responseText);
}
}
}
}
ajax({
type:'get',
data:"name:",
url:'www.baidu.com',
dataType:'json',
})
函数类型接口
对于方法传入的参数 以及返回值进行约束
1.加密函数类型接口
//加密的函数类型接口
interface encrypt{
(key:string,value:string):string;
}
var md5:encrypt = function(key:string,value:string):string{
return key+value;
}
md5('name','zahngsan')
2.可索引接口:数组约束
2.1数组对象的约束
// ts定义数组的方式
var arr:number[]=[12,12];
var arr1:Array<string>=['111','222'];
//ts中接口定义数组的方式
interface UserArr{
[index:number]:string;
}
var arr2:UserArr = ['1212','1212121']
console.log(arr2[0]);
2.2可索引接口对于对象的约束
3.类类型接口 对于类的约束
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+"后")
}
}
//接口扩展:接口可以继承接口
interface Animal {
eat():void;
}
interface Person extends Animal {
work():void;
}
泛型概念
软件工程中,我们不仅需要创建一致性良好的API同时也是需要考虑重用性。组建不仅能够支持当前的数据类型,同时也是能够支持未来的数据类型
泛型主要是用来解决 类 接口 方法的复用性,以及对不特定数据类型的支持
泛型函数
//只能返回string类型数据
function getData(value:string):string{
return value;
}
//同时返回string类型和number类型
function fetData1(value:any):any{
return value;
}
//放弃了类型检查
// T表示泛型。具体什么类是调用这个方法的时候决定的
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
getData<String>('aa');
泛型类
//泛型类:比如有一个最小堆算法,需要同时只是返回数字和字符串两种类型
//通过类的泛型来实现
class MinClass{
public list:number[]=[];
add(num:number){
this.list.push(num);
}
min(){
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(2);
m.add(333);
m.add(11111);
m.add(454545);
m.min();
//改进版
class MinClass<T>{
public list:T[]=[];
add(num:T):void{
this.list.push(num);
}
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 m=new MinClass<number>();
m.add(2);
m.add(333);
m.add(11111);
m.add(454545);
泛型接口
//函数类型接口
interface ConfigFn{
(value1:string,value2:string):string;
}
var setData:ConfigFn = function(value1:string,value2:string):string{
return value1+value2;
}
setData('name','张三');
// 泛型类型接口
interface ConfigFn{
<T>(value1:T):T;
}
var getData:ConfigFn = function<T>(value:T){
return value;
}
getData<string>('asa');
interface ConfigFn{
<T>(value1:T):T;
}
function getData<T>(value:T):T{
return value;
}
var myGetData:ConfigFn<string>=getData;
myGetData('23')
// 泛型类深入讲解
// 1.定义一个类
// 2.把类作为参数约束数据传入的类型
class User{
username:string | undefined;
password:string | undefined;
}
class MysqlDb{
add(user:User):boolean{
return true;
}
}
var u =new User();
u.username = '张三';
u.password = '123456';
var Db = new MysqlDb();
Db.add(u);
class ArtucleCate{
title:string |undefined;
desc:string |undefined
status:number |undefined;
}
class MysqlDb{
add(info:ArtucleCate):boolean{
console.log(info);
return true;
}
}
var a =new ArtucleCate();
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;
}
}
//想给user表增加数据
// 1、定义一个;User类和数据库进行映射
class User{
username:string | undefined;
password:string | undefined;
}
var u = new User();
u.username = "张三";
u.password = "123456";
var Db =new MysqlDb();
//2定义一个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;
}
}
class MysqlDb<T>{
add(info:T):boolean{
console.log(info);
return true;
}
}
var a = new ArticleCate({
title:"分类",
desc:"1111"
});
var Db =new MysqlDb<ArticleCate>();
Db.add(a)
TypeScript 类型、接口、类 、泛型 综合使用–TypeScript封装统一操作Mysql Mongodb Mssql的底层类库
/**
*
* 功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb
* 要求1: Mysql MsSql MOngoDb 功能一样 都有add updata delete get方法
*
* 注意:约束统一的规范、以及代码的重用
*
* 解决方案:需要约束规范所以要定义接口,需要代码重用所以要用到泛型
* 1.接口:在面向对象的编程中,接口是一种定义规范,他定义了行为和动作规范
* 2.泛型:通俗来说就是解决 类、接口、方法的复用性
*
*/
interface DBI<T>{
add(info:T,id:number):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, id: number): boolean {
throw new Error("Method not implemented.");
}
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[] {
throw new Error("Method not implemented.");
}
}
//定义一个操作mysql数据库的类
class MySqlDb<T> implements DBI<T>{
add(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
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[] {
throw new Error("Method not implemented.");
}
}
//操作用户表 定义一个User类和数据表做映射
class User{
username:string |undefined;
password:string |undefined;
}
var u = new User();
u.username = "张三";
u.password = "1234";
var oMysql=new MySqlDb<User>();
oMysql.add(u);
模块以及模块化封装
内部模块称作是命名空间
外部模块称作是模块,在自身的作用域运行
引入
import {getData} from './xxx/asa'
命名空间
避免命名冲突
namespac A{
}
如果需要直接export就行了
装饰器
装饰器:装饰器是一种特殊的沈明,他能够被加到类声明,方法,属性或者是参数上,可以修改类的行为
通俗的讲装饰器就是一个方法:可以注入到类、方法、属性参数上扩展类、属性、方法、参数的功能
常见的装饰器:类装饰器、属性装饰器、方法装饰器、参数装饰器
装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可以传参)
装饰器是js最大的成就之一,ES7标准特性之一
//类装饰器:在类声明之前就被声明
//1.类装饰器
//装饰器
function LogClass(params:any){
console.log(params);
//params就是当前类
params.protitype.run = function(){
}
params.protitype.age = 22;
}
//调用装饰器
@LogClass
class HttpClient {
constructor(){
}
getData(){
}
}
类装饰器 装饰器工厂
可以传参
function LogClass(params:string){
return function(target:any){
console.log(target);
console.log(params);
target.prptotype.apiUrl = params;
}
}
@LogClass('hello')
class HttpClient{
constructor(){
}
getData(){
}
}
var http = new HttpClient();
1、类装饰器
下面是一个重载构造函数的例子。
类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。
如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。
*/
/*
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、属性装饰器
属性装饰器表达式会在运行时当作函数被调用,传入下列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、方法装饰器
它会被应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义。
方法装饰会在运行时传入下列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');
*/
/*
4、方法参数装饰器
参数装饰器表达式会在运行时当作函数被调用,传入下列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();