1.TS概述
1.1 TS相比于js的優(yōu)勢:
優(yōu)勢一:類型化思維方式线梗,提前發(fā)現(xiàn)錯(cuò)誤椰于,減少改bug時(shí)間;
優(yōu)勢二:提高代碼可讀性仪搔,并使維護(hù)和重構(gòu)代碼根據(jù)容易瘾婿;
優(yōu)勢三:補(bǔ)充了接口,枚舉等開發(fā)大型應(yīng)用時(shí)js缺失的功能烤咧;
1.2.開發(fā)工具準(zhǔn)備
1.2.1 安裝解析ts工具包tsc(將ts轉(zhuǎn)化成js)
安裝:
npm i -g typescript
1.3第一個(gè)ts文件
1.3.1執(zhí)行代碼偏陪,分兩步:
1)ts -> js代碼:tsc 文件名.ts
- 執(zhí)行js:
node 文件名.js
;
解釋:
ts轉(zhuǎn)化js命令(tsc 文件名.ts
):
新建tsdemo
文件夾,新建hello.ts
文件煮嫌,在該文件目錄下打開終端笛谦,輸入tsc hello.ts
,此時(shí),文件夾就多出一個(gè)hello.js
,即可生成同名的js
代碼
執(zhí)行js命令(node 文件名.js
):
如
1.3.2簡化執(zhí)行ts步驟
問題:每次修改代碼后昌阿,都需要重復(fù)執(zhí)行tsc 文件名.ts
和node 文件名.js
命令饥脑,太繁瑣恳邀。
簡化方式:使用ts-node
包,直接在node.js中執(zhí)行js代碼(ts-node包內(nèi)部已將ts->js)灶轰,然后執(zhí)行js代碼
安裝命令: npm i -g ts-node
執(zhí)行命令:ts-node 文件名.ts
2 變量
2.1 什么是變量
兩步:1.聲明變量并指定類型 2.給變量賦值
如:第一步:let age: number = 18
2.2 ts中的數(shù)據(jù)類型
ts為了編碼規(guī)范谣沸,增加了類型校驗(yàn),提供以下數(shù)據(jù)類型:
布爾類型(boolearn
);
數(shù)字類型(number
);
字符串類型(string
);
數(shù)組類型(array
);
元組類型(tuple
);
枚舉類型(enum
);
任意類型(any
);
null和undefined
;
void
類型;
never
類型
1).布爾類型
var flag:boolean = true;
flag = false;
console.log('flag:', flag); // false
2).數(shù)字類型
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).數(shù)組類型
// 三種方式
// 第一種:
var arr1:number[] = [11,111,111];
console.log(arr1); // [11,111,111]
// 第二種:
var arr2:Array<number> = [11,22,33];
console.log(arr2); // [11,22,33]
//第三種:
var arr0:any[] = ['233433', 33, true];
console.log(arr0); // ['233433', 33, true]
5).元組類型(tuple):屬于數(shù)組的一種笋颤,每一個(gè)位置指定一中類型
/**
*/
let arr3:[number,string] =[123, 'good'];
console.log('arr3:',arr3);
6).枚舉類型:在狀態(tài)程序中用自然語言中相應(yīng)含義的單詞來代表某一狀態(tài)
enum 枚舉名 {
標(biāo)識符[=整數(shù)常數(shù)],
標(biāo)識符[=整數(shù)常數(shù)],
...
標(biāo)識符[=整數(shù)常數(shù)]
}
//如果標(biāo)識符沒有賦值乳附,它的值就是下標(biāo)
enum Color {red,green=4, 'orange'};
let thisColor_red:Color = Color.red;
let thisColor_green :Color=Color.green;
let thisColor_orange :Color=Color.orange;
// 如果標(biāo)識符沒有賦值,它的值就是下標(biāo)
console.log(thisColor_red); // 0
// 賦值
console.log('thisColor_green:', thisColor_green); // 4
// 改變下標(biāo)
console.log('thisColor_orange:', thisColor_orange); // 5
7).任意類型(any)
var num9: any = 123;
num9= 'str';
num9 = true;
console.log('num9:', num9); // true
//使用Object會(huì)報(bào)錯(cuò)伴澄,ts沒有Object類型赋除,可使用any
// var oBox:any =document.getElementById('box');
// oBox.style.color = 'red';
8).null 和 undefined其它類型的子類型
//可能是undefined,錯(cuò)誤寫法
var num11:number;
console.log(num11); //聲明未賦值非凌,會(huì)報(bào)錯(cuò) 輸出:undefined
//可能是undefined贤重,正確寫法
var num12:undefined;
console.log(num12); //輸出:undefined
//可能是null時(shí)
var num13 :null;
num13 = null;
console.log(num13); // null
//可能是null,可能是undefined時(shí)
var num15:number | null | undefined;
num15 = 1234;
console.log(num15); // 1234
9).void類型:表示方法沒有返回任何類型
// 錯(cuò)誤寫法
// function run(): undefined {
// console.log('run');
// }
// run();
//正確寫法
function running(): void {
console.log('123'); // 123
}
running();
10). never類型:是其他類型(包括null和undefined)的子類型清焕,代表從不會(huì)出現(xiàn)的值
這意味著聲明never的變量只能被never類型所賦值
// var a:never;
// a = (()=>{
// throw new Error('錯(cuò)誤');
// })();
3.函數(shù)
1).以前es5:函數(shù)聲明
// 函數(shù)的定義
function run() {
return 'run1';
}
// 匿名函數(shù)
var run2 = function() {
return 'run2'
}
2).ts函數(shù)聲明
function runTs():string {
return 'run1';
}
// 匿名函數(shù)
var run2Ts = function():string {
return 'run2ts'
}
//函數(shù)調(diào)用
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).方法可選參數(shù)時(shí)并蝗,加 ?
es5里面方法的實(shí)參和形參可以不一樣秸妥,但還是ts中必須一樣滚停,如果不一樣就需要配置
function getInfoTss(name:string, age?:number) {
return `${name}----${age}`;
}
getInfoTss('sum');// sum
// 注意:可選參數(shù)必須配置到參數(shù)的的后面
6).默認(rèn)參數(shù)
es5里面沒法設(shè)置默認(rèn)參數(shù),es6和ts都可以設(shè)置默認(rèn)參數(shù)
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).剩余參數(shù) 三點(diǎn)運(yùn)算符
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).函數(shù)重載:
java中:重載指的是兩個(gè)或者兩個(gè)以上同名函數(shù)粥惧,但它們的參數(shù)不一樣键畴,這時(shí)會(huì)出現(xiàn)函數(shù)重載的情況
ts中的重載:通過為同一個(gè)函數(shù)提供多個(gè)函數(shù)類型定義來實(shí)現(xiàn)多重功能的目的
ts為了兼容ES5以及es6重載的寫法和java中有區(qū)別
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)); //錯(cuò)誤寫法
3.類
es5中的類
1)最簡單的類
function Person1() {
this.name = 'lily';
this.age = 34;
}
var p = new Person1;
console.log(p.name);
2).構(gòu)造函數(shù)和原型鏈里面增加方法
//原型鏈上面的屬性會(huì)被多個(gè)實(shí)例共享,構(gòu)造函數(shù)不會(huì)
function Person() {
// 屬性
this.name = 'sam';
this.age = 20;
// 方法
this.run = function () {
console.log(this.name + '在運(yùn)動(dòng)');
}
}
//原型鏈
Person.prototype.sex = "男";
Person.prototype.work = function () {
console.log(this.name + '工作');
}
var p = new Person();
p.work(); //sam工作
3).類的靜態(tài)方法
Person.getInfo = function () {
console.log('靜態(tài)方法');
}
Person.getInfo();
4).構(gòu)造函數(shù)
function Person3() {
// 屬性
this.name = 'lucy';
this.age = 20;
// 方法
this.run = function () {
console.log(this.name + '在運(yùn)動(dòng)');
}
}
Person3.prototype.sex = "女";
Person3.prototype.work = function () {
console.log(this.name + '逛街la');
}
//web類 繼承Person類 原型鏈+對象冒充的組合繼承模式
function Web(){
}
//原型鏈實(shí)現(xiàn)繼承,可以繼承構(gòu)造函數(shù)里面的屬性和方法突雪,也可以繼承原型鏈上的屬性和方法
Web.prototype=new Person3();
var w =new Web();
w.work() //lucy逛街la
w.run() //lucy在運(yùn)動(dòng)
5)傳參時(shí):構(gòu)造函數(shù)和原型鏈實(shí)例化子類的時(shí)候沒法給父類傳參,用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中實(shí)現(xiàn)繼承
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.枚舉
存在一種特殊的非計(jì)算的常量枚舉成員的子集:字面量枚舉成員起惕。 字面量枚舉成員是指不帶有初始值的常量枚舉成員,或者是值被初始化為
任何字符串字面量(例如: "foo"咏删, "bar"惹想, "baz")
任何數(shù)字字面量(例如: 1, 100)
應(yīng)用了一元 -符號的數(shù)字字面量(例如: -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.類型兼容性
函數(shù)參數(shù)雙向協(xié)變
當(dāng)比較函數(shù)參數(shù)類型時(shí),只有當(dāng)源函數(shù)參數(shù)能夠賦值給目標(biāo)函數(shù)或者反過來時(shí)才能賦值成功督函。 這是不穩(wěn)定的嘀粱,因?yàn)檎{(diào)用者可能傳入了一個(gè)具有更精確類型信息的函數(shù),但是調(diào)用這個(gè)傳入的函數(shù)的時(shí)候卻使用了不是那么精確的類型信息辰狡。 實(shí)際上锋叨,這極少會(huì)發(fā)生錯(cuò)誤,并且能夠?qū)崿F(xiàn)很多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((<MouseEvent>e).x + ',' + (<MouseEvent>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均可迭代一個(gè)列表娃磺;但是用于迭代的值卻不同,for..in迭代的是對象的 鍵 的列表叫倍,而for..of則迭代對象的鍵對應(yīng)的值
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"
}
另一個(gè)區(qū)別是for..in可以操作任何對象偷卧;它提供了查看對象屬性的一種方法嘿般。 但是 for..of關(guān)注于迭代對象的值。內(nèi)置對象Map和Set已經(jīng)實(shí)現(xiàn)了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構(gòu)造函數(shù)創(chuàng)建的,是不可改變且唯一的,也可以被用做對象屬性的鍵,也可以與計(jì)算出的屬性名聲明相結(jié)合來聲明對象的屬性和類成員,
const getClassNameSymbol = Symbol();
class C {
[getClassNameSymbol](){
return "C";
}
}
let c = new C();
let className = c[getClassNameSymbol](); // "C"