TS简介 Ts微软开发,包含ES6、包含ES5 编译 tsc xx.ts 每一次都得编译,可以自动编译 开发工具中配置typescirpt自动编译 vscode: 创建tsconfig.json文件 tsc --init 生成配置文件 tsconfig.json配置文件中,修改outDir配置项,取消注释然后修改为.js vscode中,点击上方栏位run task,选择ts监听 完成 TS类型 与es5中的区别 // es5:类型变化不报错 var flag = true; flag = 234; // ts:必须指定类型 typescript var flag:boolean=true; flag = 131;//报错 TS类型: 1.boolean 2.number 3.string 4.array数组: 方式1:var arr:number[] = [1,2,3]//制定arr里面全是数字 方式2:var arr:Array= [1,2,3] 5.元组类型(tuple) 方式1:属于数组的一种,即数组中每一个元素指定类型 方式2:var arr:[number, string]=[123,“this is ts”]; 6.枚举类型(enum) // 常用来标识状态码 enum Flag{ success=1, error=2 } let f:Flag=Flag.error; console.log(f);// 2 // 如果 没有标识符没有赋值,那么打印的就是下标 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 // 常用来标识状态码 enum Err{ 'undefined'=-1, 'null'=-2, } var c:Err=Err.null console.log(c) // -2 7.任意类型any 类似ES5不指定变量类型的var var num:any=123; num = true;// 不报错 8.null类型和undefined其他数据类型的子类型 变量定义之后没有赋值,报undefined // 一个元素可能是number类型,可能是null或者undefined var num:number | undefined | null; 9.void,和java一样 没有返回值类型 // 如果方法没有返回值 function run():void{ console.log('asdf') } // 如果方法有返回值: function run():number{ return 1; } 10.never类型,代表从来不会出现的值,是其他类型(包括null‘和undefined)的子类型,代表从不会出现的值 自己理解为上述类型之外的数据类型 // 如下,接收Err类型的数据 var a:never; a = undefined;//报错 a = (()=>{ new Throw Err("报错") })() 函数的定义 ES5中: // 函数声明法 function run(){ return ... } //匿名函数 var run2 = function(){ return .. } TS中: //函数声明法 function run():number{ return 123; } // 匿名函数 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; } 方法可选参数 // es5里方法实参和形参可以不一样,但是ts必须一致,如果不一样就需要配置可选参数 参数后边加?可以设置参数可选传 可选参数必须配置到参数的最后边 function getInfo(name:string, age?number):string{ return … } 默认参数 // 默认参数,直接在形参赋值 function getInfo(name:string, age:number=20):string{ return… } 剩余参数 function sum(a:number, b:number, c:number, d:number):number{ return a+b+c+d; } // 三点运算符:接收不固定参数的(剩余参数)的值 function sum(…rest:number[]):number{ var sum= 0 ; for(var i=0; i<rest.length;i++){ sum+=rest[i]; } return sum; } 函数重载 // 类似java,同名但是不同参数的多个函数方法 // ts为了兼容es5,以及es6,和java有区别 // es5中,出现同名方法时候,下面的方法会替换上面的方法 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; } } 箭头函数 箭头函数里面的this指向上下文 类 1、ES5中定义类: function Person(){ this.name='张三'; this.age = 20; } var p = new Person(); alert(p.name); 2、构造函数和原型链里面定义 // 声明的构造方法 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } var p = new Person(); p.work(); 3、静态方法 4、es5中的继承-对象冒充继承 // 要实现Web类 继承 Person类 原型链+对象冒充的组合继承模式 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } // 要实现Web类 继承 Person类 function Web(){ Person.call(this); //对象冒充继承 } var w = new Web(); w.run();//执行父类Person的run,对象冒充可以继承构造函数里面的属性和方法 w.work();// 对象冒充可以继承构造函数的属性和方法 但是没办法继承原型链的属性和方法(prototype) 关于call: function add(c, d) { return this.a + this.b + c + d; } const obj = { a: 1, b: 2 }; console.error(add.call(obj, 3, 4)); // 10 大统上的说法就是,call改变了this的指向。然后,介绍this xxx什么一大堆名词,反正不管你懂不懂,成功绕晕你就已经ok了,但是实际发生的过程,可以看成下面的样子。 const o = { a: 1, b: 2, add: function(c, d) { return this.a + this.b + c + d } }; 给o对象添加一个add属性,这个时候 this 就指向了 o, o.add(5,7)得到的结果和add.call(o, 5, 6)相同。 5、原型链继承方法 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } // web原型链方式继承 person function web(){ } web.prototype= new person();// 原型链继承 web.work();// 可以工作,可以继承原型链属性方法 6、原型链实现继承的问题??无法给父类传参 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } var p = new person('李四', 20); p.run(); // 没问题 // 继承,无法给父类传参 function Web(name,age){ } Web.prototype= new Person(); var w = new Web('sss', 20); w.run();// 父类会alert出来“undefiend在运动” // 实例化子类时候没法给父类传参 7、原型链+构造函数的组合继承模式 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } var p = new person('李四', 20); p.run(); // 没问题 // 继承,无法给父类传参 function Web(name,age){ Person.call(this,name,age); // 对象冒充继承 可以继承构造函数里面的属性和方法 实例化子类可以给父类传参 } Web.prototype = new Person();// 实例化 var w = new Web('sss', 20); w.run();// 父类会alert出来“undefiend在运动” // 实例化子类时候没法给父类传参 8、原型链+对象冒充的另一种写法 function Person(){ this.name = "张三"; this.age=20; this.run = function()){ alert(this.name+"在运动"); } } // 原型链的属性和方法 Person.prototype.sex="男"; Person.prototype.work=function(){ alert(xx) } var p = new person('李四', 20); p.run(); // 没问题 // 继承,无法给父类传参 function Web(name,age){ Person.call(this,name,age); // 对象冒充继承 可以继承构造函数里面的属性和方法 实例化子类可以给父类传参 } Web.prototype = Person.prototype; // 和方法7中不同的是这里!!! var w = new Web('sss', 20); w.run();// 父类会alert出来“undefiend在运动” // 实例化子类时候没法给父类传参 类的定义 1、ts中定义类,类似java: class Person(){ name:string; //属性 前面省略了private construtor(n:string){ this.name = n; } run():void{ log(this.name); } } 2、继承 class Web extends Person{ constructor(name:string){ super(name); } } var w = new Web("李四"); alert(w.run()); 3、类里面的修饰符 ts提供了三种修饰符: public(默认的): 公有 在类里面、子类类外边都可以访问 protected:在类里面、子类里面可以访问、在类外部无法访问 private:在类里面可以访问、子类、类外部没法访问 静态属性 静态方法 function Person(){ this.run1=function(){// 实例方法 } } Person.run2=function(){} // 静态方法 调用实例方法:(实例化之后才能调用的) var p = new Person(); p.run1(); 调用静态方法: Person.run2(); 为什么会有静态方法和实例方法之分? JQuery的实例方法css()方法和静态方法$.get()方法大概原码为: // 生命一个节点/元素对象 function Base(element){ this.element = 获取dome节点的方法; this.css = function(str, value){ this.element.style[str] = value; } } // $方法去实例化这个BAse对象、实例方法 function $(element){ return new Base(element); // 实例化一个方法 } // 静态方法get $.get(){ 。。。 } // 那么css调用时候就可以这样写 实例方法: $("#box").css("color", "red"); 静态方法: $.get('url', function(){ ) 另一种方式声明静态方法,利用static关键字声明: class Person{ public name:string; static sex = "男"; constructor(name:string){ this.name = name; } static print(){// 静态方法 里面没办法直接调用类里面的属性, alert("静态方法:"+Person.sex);// 如果调用this.name就会报错!!! } } // $.get(){// jq里面的get就是静态方法 } 多态 父类定义一个方法不去实现,让继承他的子类去实现,每一个子类都有不同的表现 抽象方法 // 用来定义一个标准 // ts中的抽象类,它是提供其他类继承的基类,不能直接被实例化 // 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现 // abstract 抽象方法只能放在抽象类中 // 抽象类和抽象方法用来定义标准,基类要求他的子类必须包含某种方法 // 抽象方法只能出现在抽象类中 // 抽象类中必须包含至少一个抽象方法,不然没有意义 abstract class Animal{ // 省略构造方法 abstract eat():any; } // 抽象类无法直接实例化 var a = new Animal();// 这句话是错的 class Dog extends Animal{ // 省略构造方法 eat(){ console.log(this.name + '吃'); } } var d = new Dog("sss") d.eat();// sss吃 接口 // 也是定义标准,定义了行为和动作的规范 1、属性接口 // 定义了这个方法的参数是jsonObjec,而且必须有 function printLabel(labelInfo:{label:string}):void{ console.log(labelInfo.label); } printLabel("ssss"); // 错误 printLabel({name:"asdf"}); // 错误 printLabel({label:"sss"}); // 正确,打印sss 2、接口,对批量方法进行约束 // 对批量方法传入参数进行约束 // 传入对象的约束 // 声明类型 interface FullName{ firstName:string; // 注意是;结束 secondName:string; } // 方法名中引用FullName类型 function printName(name:FullName){ log(name.firstName +" "+ name.secondName); } // 调用方式一(下方调用方式是会报错的,interface定义的属性object只能包含firstName和secondName) printName({ age:20, firstName: "张", secondName: "三" }) // 调用方式二,下方引入其他的object即可忽略多余参数 var obj = { age:20, firstName: "张", secondName: "三" }; printName(obj);// 这个不报错 3、接口、可选属性,加?问号表示可传可不传 interface FullName{ firstName:string; secondName?:string;// secondName可传可不传 } 4、模拟封装一个ajax interface Config{ type:string; url:string; data?:string; dataType:string; } 5、函数类型接口、对方法传入的参数、以及返回值进行约束、批量约束 // 例子:定义加密的函数类型接口 interface encrypt{ // 定义了函数参数为string、value,返回string (key:string,value:string):string; } var md5:encrypt=function(key:string, value:string):string{ // 实现encrypt类型的函数 return key+value;//模拟下 } 6、可索引接口:对数组、对象的约束 ts定义数组方法: var arr:number[]=[123,234]; var arr1:Array = ['123', '222']; // 对数组的约束,数组类型接口 interface UserArray{ // 表示数组中index必须是number,value必须是string [index:numer]:string; } var arr:UserArray=['123', '22312']; // 对对象的约束,对象类型接口 interface UserObj{ [index:string]:string; } var obj:UserObj={name:"2342"}; // 对类的约束,类类型接口,和抽象类有点相似 interface Animal{ // 规定实现类必须要有name属性和eat方法 name:string; eat(str:string):void; } class Dog implements Animal{ name:string;// 若没此属性,ts会编译报错 constructor(name:string){ this.name = name; } eat(){ log("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必须定义 eat(){ log(this.name+"吃") } // work也必须定义 work(){ log(this.name+"工作") } } interface Animal{ eat():void; } interface Person extends Animal{ work():void; } class Programmer{ 构造方法省略 coding(code:string){ log(this.name+ " "+code) } } class Web extends Programmer implements Person{ public name:string; constructor(name:string){ this.name = name; } // eat必须定义 eat(){ log(this.name+"吃") } // work也必须定义 work(){ log(this.name+"工作") } } 泛型 和any有什么区别? any放弃了类型检查 如果想做到传入什么类型就返回什么类型,例如传入number就返回number,这时候就可以使用泛型 function getData(value:any):any{ return ""//什么类型都可以 } 泛型: 软件工程中,我们不仅要创建一致的定义好的API,同时也要考虑可重用性,组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能 在像c#和java中,可以使用泛型来创建可重用的组件,一个组件可支持多种类型的数据,这样用户就可以以自己的数据类型来使用组件 通俗理解:泛型就是解决 类 接口 方法的重用性、以及对不特定数据类型的支持 可以支持不特定的数据类型 function getData(value:T):T{ return value;//传入什么返回什么 } // 这样调用 getData(123123); getData("12131"); // 也可以写成: function getData(value:T):any{ return value;//传入什么返回什么 } // 泛型类,比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现,示例: // 定义泛型类 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(2); log(m.min());// 2 但是上边的只能传入数字类型,是否可以用泛型解决?可以: class MinClass{ 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; } } // 调用,实例化时候要先声明参数类型(); m1.add(2); m1.add(4); log(m.min());// 2 函数类型接口 指定特殊类型的方法: interface ConfigFn{ (value1:string, value2:string):string; } var setData:ConfigFn=function(value1:string, value2:string):string{ return value1 + value2; } setData("name", "张三); 泛型接口写法1: interface Config{ (value:T):T; } var getData:ConfigFn=function(value:T):T{ return value; } getData("张三"); 泛型接口写法2: interface Config{ (value:T):T; } function getData(value:T):T{ return value; } var myGetData:ConfigFn=getData; myGetData("张三"); // 把类作为参数来约束数据传入的类型 class User{ username:string | undefined; password:string | undefined; } class MySqlDb{ add(user:User):boolean{ console.log(user); retrun true; } } // 调用 var u = new User(); u.username="张三"; u.password="123456"; var Db = new MySqlDb(); Db.add(u);// console.log(u) // 上述方法可以改为泛型类 // 操作数据库的泛型类,这样可以规范插入数据库数据的类规范 class MySqlDb{ add(info:T):boolean{ log(info); return true; } } // 想给User表增加数据 // 1、定义一个User类 和数据库进行映射 class User{ username:string | undefined; password:string | undefined; } var u = new User(); u.username= '张三'; u.password="2312"; var Db = new MySqlDb();// 这一步很关键,要定义User类型 Db.add(u); // 2、文章类,数据库映射 class Article{ title:string | undefined; desc:string | undefined; status:number | undefined; constructor(params:{ title:string | undefined; desc:string | undefined; status?number | undefined;// status可选参数 }){ this.title=params.title; this.desc=params.desc; this.status=params.status; } } // 调用 var a = new Article({ title:"分类", desc:"111", status:1 }) //类当前参数的泛型类 var Db = MySqlDB
ts学习(初)文章格式乱了
发布于 2021-10-18 126 次阅读
Comments | NOTHING