1.TS概述
1.1 TS相比于js的优势:
优势一:类型化思维方式,提前发现错误,减少改bug时间;
优势二:提高代码可读性,并使维护和重构代码根据容易;
优势三:补充了接口,枚举等开发大型应用时js缺失的功能;
1.2.开发工具准备
1.2.1 安装解析ts工具包tsc(将ts转化成js)
安装:
npm i -g typescript
1.3第一个ts文件
1.3.1执行代码,分两步:
1)ts -> js代码:tsc 文件名.ts
- 执行js:
node 文件名.js
;
解释:
ts转化js命令(tsc 文件名.ts
):
新建tsdemo
文件夹,新建hello.ts
文件,在该文件目录下打开终端,输入tsc hello.ts
,此时,文件夹就多出一个hello.js
,即可生成同名的js
代码
执行js命令(node 文件名.js
):
如
1.3.2简化执行ts步骤
问题:每次修改代码后,都需要重复执行tsc 文件名.ts
和node 文件名.js
命令,太繁琐。
简化方式:使用ts-node
包,直接在node.js中执行js代码(ts-node包内部已将ts->js),然后执行js代码
安装命令: npm i -g ts-node
执行命令:ts-node 文件名.ts
2 变量
2.1 什么是变量
两步:1.声明变量并指定类型 2.给变量赋值
如:第一步:let age: number = 18
2.2 ts中的数据类型
ts为了编码规范,增加了类型校验,提供以下数据类型:
布尔类型(boolearn
);
数字类型(number
);
字符串类型(string
);
数组类型(array
);
元组类型(tuple
);
枚举类型(enum
);
任意类型(any
);
null和undefined
;
void
类型;
never
类型
1).布尔类型
var flag:boolean = true;
flag = false;
console.log('flag:', flag); // false
2).数字类型
var num:number =123;
num = 234;
console.log('num:', num); // 234
3).string类型
var str:string ='hello';
str = 'hi';
console.log('str:', str); // hi
4).数组类型
// 三种方式
// 第一种:
var arr1:number[] = [11,111,111];
console.log(arr1); // [11,111,111]
// 第二种:
var arr2:Array = [11,22,33];
console.log(arr2); // [11,22,33]
//第三种:
var arr0:any[] = ['233433', 33, true];
console.log(arr0); // ['233433', 33, true]
5).元组类型(tuple):属于数组的一种,每一个位置指定一中类型
/**
*/
let arr3:[number,string] =[123, 'good'];
console.log('arr3:',arr3);
6).枚举类型:在状态程序中用自然语言中相应含义的单词来代表某一状态
enum 枚举名 {
标识符[=整数常数],
标识符[=整数常数],
...
标识符[=整数常数]
}
//如果标识符没有赋值,它的值就是下标
enum Color {red,green=4, 'orange'};
let thisColor_red:Color = Color.red;
let thisColor_green :Color=Color.green;
let thisColor_orange :Color=Color.orange;
// 如果标识符没有赋值,它的值就是下标
console.log(thisColor_red); // 0
// 赋值
console.log('thisColor_green:', thisColor_green); // 4
// 改变下标
console.log('thisColor_orange:', thisColor_orange); // 5
7).任意类型(any)
var num9: any = 123;
num9= 'str';
num9 = true;
console.log('num9:', num9); // true
//使用Object会报错,ts没有Object类型,可使用any
// var oBox:any =document.getElementById('box');
// oBox.style.color = 'red';
8).null 和 undefined其它类型的子类型
//可能是undefined,错误写法
var num11:number;
console.log(num11); //声明未赋值,会报错 输出:undefined
//可能是undefined,正确写法
var num12:undefined;
console.log(num12); //输出:undefined
//可能是null时
var num13 :null;
num13 = null;
console.log(num13); // null
//可能是null,可能是undefined时
var num15:number | null | undefined;
num15 = 1234;
console.log(num15); // 1234
9).void类型:表示方法没有返回任何类型
// 错误写法
// function run(): undefined {
// console.log('run');
// }
// run();
//正确写法
function running(): void {
console.log('123'); // 123
}
running();
10). never类型:是其他类型(包括null和undefined)的子类型,代表从不会出现的值
这意味着声明never的变量只能被never类型所赋值
// var a:never;
// a = (()=>{
// throw new Error('错误');
// })();
3.函数
1).以前es5:函数声明
// 函数的定义
function run() {
return 'run1';
}
// 匿名函数
var run2 = function() {
return 'run2'
}
2).ts函数声明
function runTs():string {
return 'run1';
}
// 匿名函数
var run2Ts = function():string {
return 'run2ts'
}
//函数调用
run2Ts() //run2ts
3).ts中定义方法传参
function getInfo(name:string , age:number):string {
return `${name}----${age}`;
}
getInfo('sum',11); // sum====11
var getInfoTs = function(name:string,age:number):string{
return `${name}-${age}`;
}
getInfoTs('xiaozhang', 12); //xiaozhang 12
4).没有返回值
function run1():void {
console.log('run');
}
run1(); //run
5).方法可选参数时,加 ?
es5里面方法的实参和形参可以不一样,但还是ts中必须一样,如果不一样就需要配置
function getInfoTss(name:string, age?:number) {
return `${name}----${age}`;
}
getInfoTss('sum');// sum
// 注意:可选参数必须配置到参数的的后面
6).默认参数
es5里面没法设置默认参数,es6和ts都可以设置默认参数
function getA(name:string, age:number=20):string{
if(age){
return `${name}--${age}`;
}else{
return '${name}--haha';
}
}
alert(getA('张三')); // 张三--20
alert(getA('李',30)) // 李--30
7).剩余参数 三点运算符
function sum1(a:number,b:number,...result:number[]):number{
var sum = a + b;
for(var i = 0; i < result.length;i++){
sum+=result[i];
}
return sum;
}
console.log(sum1(1,2,3,4,5));//15
// 或者
function sum2(...result:number[]):number{
var sum = 0;
for(var i = 0; i < result.length;i++){
sum += result[i];
}
return sum;
}
console.log(sum2(1,2,3,4,5,6)); //21
8).函数重载:
java中:重载指的是两个或者两个以上同名函数,但它们的参数不一样,这时会出现函数重载的情况
ts中的重载:通过为同一个函数提供多个函数类型定义来实现多重功能的目的
ts为了兼容ES5以及es6重载的写法和java中有区别
function getReFn(name:string):string;
function getReFn(name:string,age:number):string;
function getReFn(name:string,age?:number):any{
if(age){
return '我叫:'+ name + '我的年龄是'+age;
}else{
return '我叫:'+name;
}
}
alert(getReFn('zhangsan')); // zhangsan
// console.log(getReFn('san', 20)); //san 20
// console.log(getReFn(231333)); //错误写法
3.类
es5中的类
1)最简单的类
function Person1() {
this.name = 'lily';
this.age = 34;
}
var p = new Person1;
console.log(p.name);
2).构造函数和原型链里面增加方法
//原型链上面的属性会被多个实例共享,构造函数不会
function Person() {
// 属性
this.name = 'sam';
this.age = 20;
// 方法
this.run = function () {
console.log(this.name + '在运动');
}
}
//原型链
Person.prototype.sex = "男";
Person.prototype.work = function () {
console.log(this.name + '工作');
}
var p = new Person();
p.work(); //sam工作
3).类的静态方法
Person.getInfo = function () {
console.log('静态方法');
}
Person.getInfo();
4).构造函数
function Person3() {
// 属性
this.name = 'lucy';
this.age = 20;
// 方法
this.run = function () {
console.log(this.name + '在运动');
}
}
Person3.prototype.sex = "女";
Person3.prototype.work = function () {
console.log(this.name + '逛街la');
}
//web类 继承Person类 原型链+对象冒充的组合继承模式
function Web(){
}
//原型链实现继承,可以继承构造函数里面的属性和方法,也可以继承原型链上的属性和方法
Web.prototype=new Person3();
var w =new Web();
w.work() //lucy逛街la
w.run() //lucy在运动
5)传参时:构造函数和原型链实例化子类的时候没法给父类传参,用call或者 Web.prototype= Person.prototype;
function Web4(name,age){
Person.call(this.name,age);
}
//或者原型链
Web4.prototype= Person.prototype;
3.2ts类
1).类的定义
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('sam');
console.log(p.getName()); // sam
p.setName('lili')
console.log(p.getName()); //lili
2).ts中实现继承
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
3)类作为接口使用
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
4.枚举
存在一种特殊的非计算的常量枚举成员的子集:字面量枚举成员。 字面量枚举成员是指不带有初始值的常量枚举成员,或者是值被初始化为
任何字符串字面量(例如: "foo", "bar", "baz")
任何数字字面量(例如: 1, 100)
应用了一元 -符号的数字字面量(例如: -1, -100)
enum ShapeKind {
Circle,
Square,
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
let c: Circle = {
kind: ShapeKind.Square,
// ~~~~~~~~~~~~~~~~ Error!
radius: 100,
}
5.类型兼容性
函数参数双向协变
当比较函数参数类型时,只有当源函数参数能够赋值给目标函数或者反过来时才能赋值成功。 这是不稳定的,因为调用者可能传入了一个具有更精确类型信息的函数,但是调用这个传入的函数的时候却使用了不是那么精确的类型信息。 实际上,这极少会发生错误,并且能够实现很多JavaScript里的常见模式。例如
enum EventType { Mouse, Keyboard }
interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }
function listenEvent(eventType: EventType, handler: (n: Event) => void) {
}
listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y));
listenEvent(EventType.Mouse, (e: Event) => console.log((e).x + ',' + (e).y));
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y)));
listenEvent(EventType.Mouse, (e: number) => console.log(e));
6.迭代器和生成器
for..of和for..in均可迭代一个列表;但是用于迭代的值却不同,for..in迭代的是对象的 键 的列表,而for..of则迭代对象的键对应的值
let list = [4, 5, 6];
for (let i in list) {
console.log(i); // "0", "1", "2",
}
for (let i of list) {
console.log(i); // "4", "5", "6"
}
另一个区别是for..in可以操作任何对象;它提供了查看对象属性的一种方法。 但是 for..of关注于迭代对象的值。内置对象Map和Set已经实现了Symbol.iterator方法,让我们可以访问它们保存的值。
let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";
for (let pet in pets) {
console.log(pet); // "species"
}
for (let pet of pets) {
console.log(pet); // "Cat", "Dog", "Hamster"
7.Symbol
symbol类型的值是通过Symbol构造函数创建的,是不可改变且唯一的,也可以被用做对象属性的键,也可以与计算出的属性名声明相结合来声明对象的属性和类成员,
const getClassNameSymbol = Symbol();
class C {
[getClassNameSymbol](){
return "C";
}
}
let c = new C();
let className = c[getClassNameSymbol](); // "C"