一.TypeScript基础语法
运行ts程序
1.在ts文件中:Runoob.ts
const hello :string="Hello World!"console.log(hello)
2.通过tsc命令编译
tsc Runoob.ts
3.得到js代码:Runoob.js
var hello ="Hello World!";
console.log(hello);
4.使用node来执行js代码
$ node Runoob.js
Hello World
我们可以同时编译多个ts文件:
tsc file1.ts file2.ts file3.ts
tsc常用编译参数:
空白和换行
ts会忽略 空格 , 制表符 , 换行符
区分大小写
分号是可选的,可以不写,但建议使用
ts与面向对象
理解:对现实世界理解和抽象的方法
面向对象有两个概念:对象和类
对象:类的一个实例,有状态和行为。
类:是一个模板,里面包含一类对象的行为,状态
方法:类的操作的实现步骤
面向对象编程实例:
编译前ts的代码:
classSite{name():void{console.log("Runoob")}}var obj =newSite();
obj.name();
编译后js的代码:
var Site =/** @class */(function(){functionSite(){}Site.prototype.name=function(){
console.log("Runoob");};return Site;}());var obj =newSite();
obj.name();
二.TS的基础类型
Any类型
1.跳过类型检查
let x:any=1;// 数字类型
x ='I am who I am';// 字符串类型
x =false;// 布尔类型
2.允许在编译时可选择地包含或移除类型检查
let x:any=4;
x.ifItExists();// 正确,ifItExists方法在运行时可能存在,但这里并不会检查
x.toFixed();// 正确
3.定义存储数组
let arrayList:any[]=[1,false,'fine'];
arrayList[1]=100;
null和Undefined
null
表示:1.什么都没有
2.空对象引用
3.用typeof 返回 object
undefined
表示:1.一个没有设置值的变量
2.用typeof 会返回 undefined
3.null和undefined 是任何类型的子类型,所以可以赋值给其他类型,但在严格空检验(–stricNullChecks)下,只能赋给void或其本身对应的类型
// 启用 --strictNullCheckslet x:number;
x =1;// 编译正确
x =undefined;// 编译错误
x =null;// 编译错误
never类型
表示:1.代表不会出现的值
2.声明了never只能被never类型所赋值
是其他类型(包括null和nudefined)的子类型,
let x:never;let y:number;// 编译错误,数字类型不能转为 never 类型
x =123;// 运行正确,never 类型可以赋值给 never类型
x =(()=>{thrownewError('exception')})();// 运行正确,never 类型可以赋值给 数字类型
y =(()=>{thrownewError('exception')})();// 返回值为 never 的函数可以是抛出异常的情况functionerror(message:string):never{thrownewError(message);}// 返回值为 never 的函数可以是无法被执行到的终止点的情况functionloop():never{while(true){}}
三.变量声明
用于引用计算机内存地址
变量命名规则:
- 只能包含_和$
var [变量名] : [类型] = 值;
变量作用域
- 全局作用域
- 类作用域:类变量在类的方法外,可通过类的对象访问。也可以是静态的,静态变量可以通过类名直接访问—class.valname
- 局部作用域
ts的代码
var global_num =12// 全局变量classNumbers{
num_val =13;// 实例变量static sval =10;// 静态变量storeNum():void{var local_num =14;// 局部变量}}console.log("全局变量为: "+global_num)console.log(Numbers.sval)// 静态变量var obj =newNumbers();console.log("实例变量: "+obj.num_val)
tsc编译的js代码
var global_num =12;// 全局变量var Numbers =/** @class */(function(){functionNumbers(){this.num_val =13;// 实例变量}Numbers.prototype.storeNum=function(){var local_num =14;// 局部变量};
Numbers.sval =10;// 静态变量return Numbers;}());
console.log("全局变量为: "+ global_num);
console.log(Numbers.sval);// 静态变量var obj =newNumbers();
console.log("实例变量: "+ obj.num_val);
四.运算符
位运算符
var a:number=2;// 二进制 10 var b:number=3;// 二进制 11var result;
result =(a & b);console.log("(a & b) => ",result)
result =(a | b);console.log("(a | b) => ",result)
result =(a ^ b);console.log("(a ^ b) => ",result);
result =(~b);console.log("(~b) => ",result);
result =(a << b);console.log("(a << b) => ",result);
result =(a >> b);console.log("(a >> b) => ",result);
result =(a >>>1);console.log("(a >>> 1) => ",result);
三元运算符
Test ? expr1 : expr2
var num:number=-2var result = num >0?"大于 0":"小于 0,或等于 0"console.log(result)
类型运算符
typeof 运算符
返回:操作数的数据类型
var num =12console.log(typeof num);//输出结果: number
instanceof
判断对象是否与预期的类型相同
字符串运算符:连接运算符(+)
var msg:string="RUNOOB"+".COM"console.log(msg)
五.循环
- for … in …
- for … of …
- forEach
- every
- some
1.for… in … 循环
用于一组值的集合或列表进行迭代
for(var val in list){//语句 }
实例
var j:any;var n:any="a b c"for(j in n){console.log(n[j])}
2.for…of …
for…of 允许遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等。
let someArray =[1,"string",false];for(let entry of someArray){console.log(entry);// 1, "string", false}
3.forEach
js循环语法:forEach,every,some
ts:因为forEach在iteration中是无法返回的,所以用every和some来取代foreach
let list =[4,5,6];
list.forEach((val, idx, array)=>{// val: 当前值// idx:当前index// array: Array});
4.every
let list =[4,5,6];
list.every((val, idx, array)=>{// val: 当前值// idx:当前index// array: Arrayreturntrue;// Continues// Return false will quit the iteration});
六.函数
函数返回值
// 函数定义functiongreet():string{// 返回一个字符串return"Hello World"}functioncaller(){var msg =greet()// 调用 greet() 函数 console.log(msg)}// 调用函数caller()
带参数函数
functionadd(x:number, y:number):number{return x + y;}console.log(add(1,2))
可选参数和默认参数
用?修饰,即可用可不用
functionbuildName(firstName:string, lastName?:string){if(lastName)return firstName +" "+ lastName;elsereturn firstName;}let result1 =buildName("Bob");// 正确let result2 =buildName("Bob","Adams","Sr.");// 错误,参数太多了let result3 =buildName("Bob","Adams");// 正确
默认参数
参数不能同时设置为可选和默认
functioncalculate_discount(price:number,rate:number=0.50){var discount = price * rate;console.log("计算结果: ",discount);}calculate_discount(1000)calculate_discount(1000,0.30)
剩余参数
以…为前缀,当传入的参数不确定时使用
functionbuildName(firstName:string,...restOfName:string[]){return firstName +" "+ restOfName.join(" ");}let employeeName =buildName("Joseph","Samuel","Lucas","MacKinzie");
匿名函数
函数表达式:将匿名函数赋值给一个变量
格式:
**
var res = function( [arguments] ) { ... }
**
varres=function(a:number,b:number){return a*b;};console.log(res(12,2))
匿名函数自调用
自己执行自己,不会变量提升,运行完就释放内存
(function(){var x ="Hello!!";console.log(x)})()
构造函数
利用new Function来定义函数
var res = new Function ([arg1[, arg2[, …argN]],] functionBody)
var myFunction =newFunction("a","b","return a * b");var x =myFunction(4,3);console.log(x);
递归函数
函数内调用函数本身
functionfactorial(number){if(number<=0){// 停止执行return1;}else{return(number*factorial(number-1));// 调用自身}};console.log(factorial(6));// 输出 720
Lambda函数
- ()是可选的
- 无参数时可以设置空括号
- 不指定函数的参数类型,通过函数内来推断参数类型
也被称为箭头函数,,比较简洁,,建议常用
( [param1, parma2,…param n] )=>statement;
varfoo=(x:number)=>10+ x
console.log(foo(100))//输出结果为 110
()是可选的
vardisplay= x =>{console.log("输出为 "+x)}display(12)
无参数时可以设置空括号
vardisp=()=>{console.log("Function invoked");}disp();
不指定函数的参数类型,通过函数内来推断参数类型
varfunc=(x)=>{if(typeof x=="number"){console.log(x+" 是一个数字")}elseif(typeof x=="string"){console.log(x+" 是一个字符串")}}func(12)func("Tom")
函数重载
方法名相同,而参数不同
functiondisp(s1:string):void;functiondisp(n1:number,s1:string):void;functiondisp(x:any,y?:any):void{console.log(x);console.log(y);}disp("abc")disp(1,"xyz");
七.Number
是一个原始类
var num = new Number(value);
注意: 如果一个参数值不能转换为一个数字将返回 NaN (非数字值)。
console.log("TypeScript Number 属性: ");console.log("最大值为: "+ Number.MAX_VALUE);console.log("最小值为: "+ Number.MIN_VALUE);console.log("负无穷大: "+ Number.NEGATIVE_INFINITY);console.log("正无穷大:"+ Number.POSITIVE_INFINITY);
NaN实例
var month =0if( month<=0|| month >12){
month = Number.NaNconsole.log("月份是:"+ month)}else{console.log("输入月份数值正确。")}//输出结果:月份是:NaN
prototype实例
functionemployee(id:number,name:string){this.id = id
this.name = name
}var emp =newemployee(123,"admin")
employee.prototype.email ="[email protected]"console.log("员工号: "+emp.id)console.log("员工姓名: "+emp.name)console.log("员工邮箱: "+emp.email)
八.String(字符串)
用于处理文本
String对象属性
方法省略
八.Array(数组)
如果在声明的时候没有设置类型,默认为any类型
声明时直接初始化
var nums:number[]=[1,2,3,4]console.log(nums[0]);console.log(nums[1]);console.log(nums[2]);console.log(nums[3]);
Array
可以用其创建数组,,比较冷门
(参数一,参数二)
(数组大小的数值,初始化的数组列表使用,分隔符)
var arr_names:number[]=newArray(4)for(var i =0; i<arr_names.length; i++){
arr_names[i]= i *2console.log(arr_names[i])}
var sites:string[]=newArray("Google","Runoob","Taobao","Facebook")for(var i =0;i<sites.length;i++){console.log(sites[i])}
数组解构
var arr:number[]=[12,13]var[x,y]= arr // 将数组的两个元素赋值给变量 x 和 yconsole.log(x)console.log(y)
数组迭代
var j:any;var nums:number[]=[1001,1002,1003,1004]for(j in nums){console.log(nums[j])}
多维数组
var multi:number[][]=[[1,2,3],[23,24,25]]console.log(multi[0][0])console.log(multi[0][1])console.log(multi[0][2])console.log(multi[1][0])console.log(multi[1][1])console.log(multi[1][2])
作为参数传递给函数
var sites:string[]=newArray("Google","Runoob","Taobao","Facebook")functiondisp(arr_sites:string[]){for(var i =0;i<arr_sites.length;i++){console.log(arr_sites[i])}}disp(sites);
作为函数的返回值
functiondisp():string[]{returnnewArray("Google","Runoob","Taobao","Facebook");}var sites:string[]=disp()for(var i in sites){console.log(sites[i])}
九.Map对象
保存键值对,并且能够记住键的原始插入顺序
创建Map
let myMap = new Map();
初始化Map,可以以数组的格式来传入键值对
let myMap =newMap([["key1","value1"],["key2","value2"]]);
相关的函数与属性
let nameSiteMapping =newMap();// 设置 Map 对象
nameSiteMapping.set("Google",1);
nameSiteMapping.set("Runoob",2);
nameSiteMapping.set("Taobao",3);// 获取键对应的值console.log(nameSiteMapping.get("Runoob"));// 2// 判断 Map 中是否包含键对应的值console.log(nameSiteMapping.has("Taobao"));// trueconsole.log(nameSiteMapping.has("Zhihu"));// false// 返回 Map 对象键/值对的数量console.log(nameSiteMapping.size);// 3// 删除 Runoobconsole.log(nameSiteMapping.delete("Runoob"));// trueconsole.log(nameSiteMapping);// 移除 Map 对象的所有键/值对
nameSiteMapping.clear();// 清除 Mapconsole.log(nameSiteMapping);
使用ES6编译
tsc --target es6 test.ts
迭代Map
Map对象中的元素是按顺序插入的,每一次迭代返回[key,value]数组,建议使用for…of
let nameSiteMapping =newMap();
nameSiteMapping.set("Google",1);
nameSiteMapping.set("Runoob",2);
nameSiteMapping.set("Taobao",3);// 迭代 Map 中的 keyfor(let key of nameSiteMapping.keys()){console.log(key);}// 迭代 Map 中的 valuefor(let value of nameSiteMapping.values()){console.log(value);}// 迭代 Map 中的 key => valuefor(let entry of nameSiteMapping.entries()){console.log(entry[0], entry[1]);}// 使用对象解析for(let[key, value]of nameSiteMapping){console.log(key, value);}
使用ES6编译
tsc --target es6 test.ts
十.元组
于数组相反,允许存储不同类型的元素,可以作为参数传递给函数
格式:var tuple_name = [value1,value2,value3,…value n]
创建元组
声明一个元组并初始化
var mytuple =[10,"Runoob"];
访问元组
var mytuple =[10,"Runoob"];// 创建元组console.log(mytuple[0])console.log(mytuple[1])
元组运算
- push() 向元组添加元素至最后
- pop(): 从元组中移除最后一个元素,并返回移除的元素
var mytuple =[10,"Hello","World","typeScript"];console.log("添加前元素个数:"+mytuple.length)// 返回元组的大小
mytuple.push(12)// 添加到元组中console.log("添加后元素个数:"+mytuple.length)console.log("删除前元素个数:"+mytuple.length)console.log(mytuple.pop()+" 元素从元组中删除")// 删除并返回删除的元素console.log("删除后元素个数:"+mytuple.length)
更新元组
元组是可变的
var mytuple =[10,"Runoob","Taobao","Google"];// 创建一个元组console.log("元组的第一个元素为:"+ mytuple[0])// 更新元组元素
mytuple[0]=121console.log("元组中的第一个元素更新为:"+ mytuple[0])
解构元组
var a =[10,"Runoob"]var[b,c]= a
console.log( b )console.log( c )
十一.联合类型
管道( | )将变量设置多种类型
var val:string|number
val =12console.log("数字为 "+ val)
val ="Runoob"console.log("字符串为 "+ val)
将联合类型作为函数参数使用
functiondisp(name:string|string[]){if(typeof name =="string"){console.log(name)}else{var i;for(i =0;i<name.length;i++){console.log(name[i])}}}disp("Runoob")console.log("输出数组....")disp(["Runoob","Google","Taobao","Facebook"])
联合类型数组
var arr:number[]|string[];var i:number;
arr =[1,2,4]console.log("**数字数组**")for(i =0;i<arr.length;i++){console.log(arr[i])}
arr =["Runoob","Google","Taobao"]console.log("**字符串数组**")for(i =0;i<arr.length;i++){console.log(arr[i])}
一十二.接口
- 是一系列抽象方法的声明
- 一些方法特征的集合
- 这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。
格式:interface interface_name {
}
interfaceIPerson{
firstName:string,
lastName:string,sayHi:()=>string}var customer:IPerson ={
firstName:"Tom",
lastName:"Hanks",
sayHi:():string=>{return"Hi there"}}console.log("Customer 对象 ")console.log(customer.firstName)console.log(customer.lastName)console.log(customer.sayHi())var employee:IPerson ={
firstName:"Jim",
lastName:"Blakes",
sayHi:():string=>{return"Hello!!!"}}console.log("Employee 对象 ")console.log(employee.firstName)console.log(employee.lastName)
联合类型和接口
在接口中使用联合类型
interfaceRunOptions{
program:string;
commandline:string[]|string|(()=>string);}// commandline 是字符串var options:RunOptions ={program:"test1",commandline:"Hello"};console.log(options.commandline)// commandline 是字符串数组
options ={program:"test1",commandline:["Hello","World"]};console.log(options.commandline[0]);console.log(options.commandline[1]);// commandline 是一个函数表达式
options ={program:"test1",commandline:()=>{return"**Hello World**";}};var fn:any= options.commandline;console.log(fn());
接口和数组
接口中我们可以将数组的索引值和元素设置为不同类型,索引值可以是数字或字符串
interfacenamelist{[index:number]:string}// 类型一致,正确var list2:namelist =["Google","Runoob","Taobao"]// 错误元素 1 不是 string 类型// var list2:namelist = ["Runoob",1,"Taobao"]
接口继承
接口通过其他接口来拓展自己
- 接口继承多个接口
- 使用关键字extends
单继承实例
interfacePerson{
age:number}interfaceMusicianextendsPerson{
instrument:string}var drummer =<Musician>{};
drummer.age =27
drummer.instrument ="Drums"console.log("年龄: "+drummer.age)console.log("喜欢的乐器: "+drummer.instrument)
多继承实例
interfaceIParent1{
v1:number}interfaceIParent2{
v2:number}interfaceChildextendsIParent1, IParent2 {}var Iobj:Child ={ v1:12, v2:23}console.log("value 1: "+Iobj.v1+" value 2: "+Iobj.v2)
十三.类
描述所创建对象共同的属性和方法
支持类和接口
注意构造函数的参数名与字段名相同
classCar{// 字段
engine:string;// 构造函数 constructor(engine:string){this.engine = engine
}// 方法 disp():void{console.log("发动机为 : "+this.engine)}}
创建实例化对象
类实例化时会调用构造函数
var obj = new Car(“Engine 1”)
classCar{// 字段
engine:string;// 构造函数constructor(engine:string){this.engine = engine
}// 方法disp():void{console.log("函数中显示发动机型号 : "+this.engine)}}// 创建一个对象var obj =newCar("XXSY1")// 访问字段console.log("读取发动机型号 : "+obj.engine)// 访问方法
obj.disp()
类的继承
- 子类不能继承父类的私有成员(方法和属性)
- 支持多重继承,但一次只能继承一个类
classShape{
Area:numberconstructor(a:number){this.Area = a
}}classCircleextendsShape{disp():void{console.log("圆的面积: "+this.Area)}}var obj =newCircle(223);
obj.disp()
继承类的方法重写
- 类继承后,子类可以对父类的方法重写
- super 是对父类的直接引用,可以调用父类的属性和方法
classPrinterClass{doPrint():void{console.log("父类的 doPrint() 方法。")}}classStringPrinterextendsPrinterClass{doPrint():void{super.doPrint()// 调用父类的函数console.log("子类的 doPrint()方法。")}}
static 关键字
- 定义类的数据成员(属性和方法)为静态的
- 静态成员可以直接通过类名调用
classStaticMem{static num:number;staticdisp():void{console.log("num 值为 "+ StaticMem.num)}}
StaticMem.num =12// 初始化静态变量
StaticMem.disp()// 调用静态方法
instanceof运算符
判断是否是指定类型的
classPerson{}var obj =newPerson()var isPerson = obj instanceofPerson;console.log("obj 对象是 Person 类实例化来的吗? "+ isPerson);
访问控制修饰符
作用:对类,变量,方法,构造方法进行保护
- Public
- protected:只允许其自身和子类访问
- private:只能自身访问
classEncapsulate{
str1:string="hello"private str2:string="world"}var obj =newEncapsulate()console.log(obj.str1)// 可访问 console.log(obj.str2)// 编译错误, str2 是私有的
类和接口
- 类可以实现接口
- 使用关键字implements
- 将interest字段作为类的属性使用
interfaceILoan{
interest:number}classAgriLoanimplementsILoan{
interest:number
rebate:numberconstructor(interest:number,rebate:number){this.interest = interest
this.rebate = rebate
}}var obj =newAgriLoan(10,1)console.log("利润为 : "+obj.interest+",抽成为 : "+obj.rebate )
十四.对象
对象:是一组包含键值对的实例。值可以是标量,数组,函数,对象
var object_name ={
key1:"value1",// 标量
key2:"value",key3:function(){// 函数},
key4:["content1","content2"]//集合}
类型模板
var sites ={
site1:"Runoob",
site2:"Google",sayHello:function(){}// 类型模板};
sites.sayHello=function(){//对象中添加方法console.log("hello "+ sites.site1);};
sites.sayHello();
对象作为参数传递给函数
var sites ={
site1:"Runoob",
site2:"Google",};varinvokesites=function(obj:{ site1:string, site2 :string}){console.log("site1 :"+obj.site1)console.log("site2 :"+obj.site2)}invokesites(sites)
鸭子类型
关注行为,不关注类型
interfaceIPoint{
x:number
y:number}functionaddPoints(p1:IPoint,p2:IPoint):IPoint {var x = p1.x + p2.x
var y = p1.y + p2.y
return{x:x,y:y}}// 正确var newPoint =addPoints({x:3,y:4},{x:5,y:1})// 错误 var newPoint2 =addPoints({x:1},{x:4,y:3})
十五.命名空间
- 解决重名问题
- 用namespace来定义
- 互不干扰
- 如果命名空间中的类和接口,需要外部调用,export
- 引用一个单独的TS,应使用///
/// <reference path = "SomeFileName.ts" />
namespace SomeNameSpaceName {exportinterfaceISomeInterfaceName{}exportclassSomeClassName{}}
实例
IShape.ts
namespace Drawing {exportinterfaceIShape{draw();}}
Circle.ts
/// <reference path = "IShape.ts" /> namespace Drawing {exportclassCircleimplementsIShape{publicdraw(){console.log("Circle is drawn");}}}
Triangle.ts
/// <reference path = "IShape.ts" /> namespace Drawing {exportclassTriangleimplementsIShape{publicdraw(){console.log("Triangle is drawn");}}}
TestShape.ts
/// <reference path = "IShape.ts" /> /// <reference path = "Circle.ts" /> /// <reference path = "Triangle.ts" /> functiondrawAllShapes(shape:Drawing.IShape){
shape.draw();}drawAllShapes(newDrawing.Circle());drawAllShapes(newDrawing.Triangle());
使用tsc命令编译
tsc --out app.js TestShape.ts
使用node查看输出结果
$ node app.js
Circle is drawn
Triangle is drawn
嵌套命名空间
Invoice.ts
namespace Runoob {exportnamespace invoiceApp {exportclassInvoice{publiccalculateDiscount(price:number){return price *.40;}}}}
Invoice Test.ts
/// <reference path = "Invoice.ts" />var invoice =newRunoob.invoiceApp.Invoice();console.log(invoice.calculateDiscount(500));
使用tsc编译
tsc --out app.js InvoiceTest.ts
使用node来查看输出结果
$ node app.js
200
十六.模块
作用:
- 更快的更换代码
- 模块里的东西外部是不可见的,是局部作用域,非全局作用域
- 通过import 和export 建立
- 模块使用模块加载器去导入其他的模块
- 运行时:模块加载器的作用是下载这个模块的所有依赖
export 模块导出
// 文件名 : SomeInterface.ts exportinterfaceSomeInterface{// 代码部分}
在另一个文件中使用import导入
import someInterfaceRef =require("./SomeInterface");
实例
IShape.ts
/// <reference path = "IShape.ts" /> exportinterfaceIShape{draw();}
Circle.ts
import shape =require("./IShape");exportclassCircleimplementsshape.IShape {publicdraw(){console.log("Cirlce is drawn (external module)");}}
Triangle.ts
import shape =require("./IShape");exportclassTriangleimplementsshape.IShape {publicdraw(){console.log("Triangle is drawn (external module)");}}
TestShape.ts
import shape =require("./IShape");import circle =require("./Circle");import triangle =require("./Triangle");functiondrawAllShapes(shapeToDraw: shape.IShape){
shapeToDraw.draw();}drawAllShapes(newcircle.Circle());drawAllShapes(newtriangle.Triangle());
使用tsc命令编译
tsc --module amd TestShape.ts
版权归原作者 ACBYCL 所有, 如有侵权,请联系我们删除。