一、TypeScript的特點 1.支持ES6規範 2.強大的IDE支持(集成開發環境) 1. 允許為變數指定類型,減少你在開發階段犯錯誤的幾率。 2. 語法提示,在IDE編寫代碼時,它會根據你所處的上下文把你能用的類,變數,方法,關鍵字給你提示出來。 3. 重構,方便的修改變數,方法,文件的名字, ...
一、TypeScript的特點
1.支持ES6規範
2.強大的IDE支持(集成開發環境)
允許為變數指定類型,減少你在開發階段犯錯誤的幾率。
語法提示,在IDE編寫代碼時,它會根據你所處的上下文把你能用的類,變數,方法,關鍵字給你提示出來。
重構,方便的修改變數,方法,文件的名字,當你修改的時候IDE會幫你把你用到過這些變數,方法的地方給修改掉。
3.Angular2的開發語言。
二、搭建TypeScipt的開發環境
1. 我們需要compiler(編譯器)。
我們需要把 .ts 結尾的TypeScript文件給編譯成 .js 結尾的JavsScript文件,因為現在有些瀏覽器是不支持ES6語法的,沒辦法直接讓程式跑起來,所以我們需要編譯成支持ES5的JavaScript語法。
2. 使用線上compiler開發 TypeScript
3. 搭建本地開發環境
npm insatll typescript -g
全局安裝tsc --version
查看版本./demo/hello.ts
tsc ./demo/hello.ts
會在它的同級目錄生成一個hello.js文件每次都這樣的操作有點麻煩,我們開始使用IDE,它可以幫我做這些事情
創建項目目錄打開CMD
tsc --init
會生成tsconfig.json配置文件{ "compilerOptions": { "target": "es5",//翻譯出來的語法 "module": "commonjs",//使用commonjs模塊 "outDir": "./js/",//翻譯出來的文件存放在./js文件夾中 "rootDir": "./tscript/",//需要翻譯的文件放在./tscript文件夾中 "esModuleInterop": true // esModuleInterop取決於設置的內容module。 // 如果有"module": "commonjs",則只需啟用"esModuleInterop": true。 // 如果您有"module": "es2015"或者"module": "esnext", //您還必須啟用"allowSyntheticDefaultImports": true以便導入CommonJS模塊(如React)作為預設值。 } }
我們採用以上配置;
我們今天用Visual Studio Code來做示範打開創建好的項目文件夾,webstorm上的話會有提示插件更加方便。
新建tscript、js文件夾,分別用作存放typescript、javascript文件,在tscript目錄中新建test.ts文件。
打開>菜單>終端>運行任務>
點擊運行後,只要我們修改ts文件的代碼且保存後會自動翻譯
這就配置好了,接下來就可以正常開發了。
三、學習字元串
1、多行字元串
JS中我們聲明變數是不可以換行的
var str = 'aaa
bbb
ccc'
/*上面這樣的寫法是會報錯的,我們通常用下麵的寫法*/
var str = 'aaa'+
'bbb'+
'ccc';
TS中有多行字元串的寫法用``
來包裹
var str = `aaa
bbb
ccc`
//在這個裡面你是可以任意換行的
//翻譯成JS是這樣的
var str = 'aaa\nbbb\nccc'
2、字元串模板
var myName = 'huoqingchi'
var getName = function () {
return 'huoqingchi';
}
console.log(`hello ${myName}`);//可以直接寫表達式
console.log(`hello ${getName()}`);//也可以直接調用方法
//切記能這樣做的原因是因為它們寫在了``當中。
接下來我們見識下字元串模板的威力,用字元串拼接一段HTML
var myName = 'huoqingchi';
console.log(`<div>
<h1>你們好我是${myName}</h1>
<h1>${getName()}</h1>
</div>`);//可讀性和書寫實在是太好了。
3、自動拆分字元串
當你在用一個字元串模板去調用一個方法的時候這個字元串模板裡面表達式的值會自動賦給被調用方法中的參數。
function test(template,name,age) {
console.log(template)
console.log(name)
console.log(age)
};
var myName = 'huoqingchi';
var getAge = function(){
return 18;
}
//如果你想使用字元串拆分的特性就不能直接圓括弧調用test方法,需要用``。
//第一個參數是你的字元串模板。
//第二個參數就是你出現的第一個表達式的值。
//第三個參數就是你出現的第二個表達式的值。
test`hello ${myName},${getAge()}`
輸出結果:
四、參數的新特性
1、參數類型
在參數的名稱後面我們可以使用冒號來指定參數的類型
因為我已經給str這個變數指定了string類型,所以我再給它賦值一個數值類型時會報錯,這種情況只會出現在我們編寫.ts文件時,當它給我們翻譯成.js文件的時候還是會被賦值數值型的。
可是上面代碼我明明沒有給它指定類型了,為什麼還是報錯呢?
這是因為TypeScript有一個類型推斷機制,如果你一次給這個變數存儲的是字元串值,它會規定你這個變數只能存儲字元串值。
如果想讓一個變數又是字元串又是數值型;
我們可以給這個變數賦值一個any類型,它代表這個變數可以存儲任何類型的值;
除了string和any類型我們還有
1、number //數值
2、boolean //true||false
3、void //用來聲明方法的返回值的void代表這個函數不需要返回值,你也可以給這個方法設置返回規定的類性。除了給方法設置類性外,我們也可以給方法的參數設置類型,規定必須傳入的參數。
4、自定義類型:
class Person {
name:string;
age:number;
}
var zhangsan :Person = new Person();
zhangsan.name = 'zhangsan'
zhangsan.age = 18;
//當你聲明好Person類型後去調用會有語法提示你它當前有那些屬性且他們的類性是什麼。
如果你聲明瞭一個變數,再聲明一個同名函數會報錯,
2、預設參數
這個時候我們可以給第三個形參設置一個預設值:
切記,需要設置預設參數的形參從後面依次排列,因為傳入的參數是從第一個開始匹配的
3、可選參數
在方法的參數聲明後面用?
來標明此參數為可選參數
這個時候運行會輸出:
使用可選參數要註意的有兩點:
1.可選參數沒傳的時候怎麼處理,b參數沒有傳入,但是如果我在函數體裡面直接去調它的話會報錯;
例子:console.log(b.lenght)
//這種錯誤非常常見undefined不能打點
2.可選參數是不可以聲明在必選參數的前面;
五、函數新特性
1、Rest and Spread 操作符
1.1聲明可以傳入任意參數的方法(主要)
function func1(...args) {//這個...就是Rest and Spread 操作符
//用...聲明的args參數可以傳入任意數量的參數
args.forEach(function (arg) {
console.log(arg)
})//args就是一個數組,它內部用的是arguments,可以去觀察翻譯後的.js文件。
};
func1(1,2,3);
func1(4,5,6,7,8);
輸出結果:
1.2 把任意長度的數組一個固定數量的方法的調用
function func1(a,b,c) {
console.log(a);//第一次傳過來的是1,2沒有第三個參數所以c是undefined
console.log(b);//第二次傳過來的是5,4,2,34,2但是我們只有a,b,c三個形參接受,所以只會拿取前三個。
console.log(c);
};
var args = [1,2];
func1(...args);//這樣的操作會把args數組裡面的每一項給出來,當做實參傳過去。
var args2 = [5,4,2,34,2];
func1(...args2);//因為TypeScript還不支持這種語法所以會報錯,但是編譯好的js文件可正常運行。
運行編譯後的js文件輸出結果:
2、generator函數
它可以控制函數的執行過程,手工暫停和恢復代碼執行。
function* get() {//在function和函數名中間加*就是generator函數
console.log("start");
yield;//yield會將函數打斷停留不繼續往下執行
console.log("finish")
}
var func1 = get();//如果你直接去調用get函數是沒用的,需要將它賦給一個變數。
func1.next();//通過調用.next()可以讓函數執行。//輸出start;
func1.next();//輸出finish,//每次調用next會讓函數執行且停留在下一個yield。
因為這個語法TypeScript暫時還不支持,它是es6規範的一部分,所以我們用到了babel翻譯。
function *get() {
while (true) {//這個迴圈沒有一直執行,只有下麵price>limit為true的時候才會執行
yield Math.random()*100;
}
}
var priceG = get();//拿到get的執行權
var limit = 15;//最低15
var price = 100;//起始100
while (price>limit) {//如果低於15就停。
price = priceG.next().value;//通過.value得到get函數中yield返回的隨機數且賦值給price
console.log(`${price}`)//輸出yield返回的值
}
console.log(`${price}`);//如果拿到了小於15的數就會最後彈出
輸出結果:
3、析構表達式
通過表達式將對象或數組拆解成任意數量的變數。
3.1 Object
function get() {
return {
xing:'huo',
age:18
}
}
var {xing,age} = get();
//{}中的變數名要跟你函數返回對象中的屬性名相同
//如果想改名字:{xingshi:xing,age}
//console.log(xingshi);//'huo'
console.log(xing);//'huo'
console.log(age);//18
function get() {
return {
xing:'huo',
yifu:{//如果你返回的又是一個對象
kuzi:400,
shangyi:200
}
}
}
//那麼我們可以再把裡面的屬性給析構
var {xing,yifu:{kuzi}} = get();
console.log(xing);//'huo'
console.log(kuzi);//400
3.2 Array
var arr1 = [1,2,3,4];
var [number1,number2] = arr1;
console.log(number1)//1
console.log(number2)//2
//如果要拿3和4
var [, , number1, number2] = arr1;
//站位,但是我不拿出來。
console.log(number1)//3
console.log(number2)//4
//如果要拿1和4
var [number1, , number2] = arr1;
console.log(number1)//1
console.log(number2)//4
3.2 析構表達式和Rest操作符共用
var arr1 = [1,2,3,4];
var [number1,number2,...shengyu] = arr1;
console.log(number1)//1
console.log(number2)//2
console.log(shengyu)//[3,4]
var arr1 = [1,2,3,4];
function test([number1, number2, ...shengyu]) {
console.log(number1)//1
console.log(number2)//2
console.log(shengyu)//[3,4]
}
test(arr1);//類型“number[]”的參數不能賦給類型“[any, any, ...any[]]”的參數,但不影響我們使用。
六、表達式與迴圈
1、箭頭表達式
用來聲明匿名函數,消除傳統匿名函數的this指向問題。
var sum = (arg1,arg2) => arg1+arg2;
這就是最簡單的一行箭頭表達式。如果返回值只有一行的話可以省略{}也不需要寫return方法。如果是多行的話是需要寫{}的。
var sum = () => {}
如果沒有參數的話是這樣的寫法。
var sum = arg => {return arg}
如果只有一個參數的話圓括弧都可以省略。
例子:
var myArray = [1,2,3,4,5,6];
console.log(myArray.filter(value => value%2 == 0))
//filter()是過慮的意思,()裡面放的是表達式,如果取餘2==0的話就返回,會得到[2,4,6]。
箭頭表達式最大的好處this指向:
function get(name:string) {
this.name = name;
// setInterval(function () {
// console.log("name is"+this.name);
// //什麼都得不到因為this指向的是window
// }, 1000);
setInterval(() => {
console.log("name is " + this.name);
//跟想得到的是一樣的,因為this是它所處的上下文
}, 1000);
}
var stock = new get("huo");
2、迴圈
1、forEach
2、for...in...
3、for...of...
七、面向對象特性
1、類(class)
類是TypeScript的核心,使用TypeScript開發時,大部分代碼都是寫在類裡面的。
這裡會介紹類的定義,構造函數,以及類的繼承。
class People {//TypeScript聲明類的方法
name;//屬性
getName(){//方法
console.log("huoqingchi");
}
//類擁有屬性和方法
}
var p1 = new People();//我們通過new實例化了這個類,且賦值給了p1
p1.name = "rope";
p1.getName();
//同樣一個類我們可以new出多個實例,且這些實例都擁有相同的屬性和方法,但是狀態不同。
var p2 = new People();//我們可以在實例化一個類,且賦值給了p2
p2.name = "scarf";
p2.getName();
訪問控制符
管理類的屬性和方法可以在哪裡調用,一共有三個,且帶聲明效果。
1、public
class People {
public name;
public getName(){
console.log("huoqingchi");
}
//public的屬性和方法都是可以在類的內部||類的外部訪問的,它也是預設的,不寫也可以。
}
2、private
3、protected
類的構造函數
class People {
constructor(){//類的構造函數就是它,一個特殊的方法。
//這個方法會在這個類實例化的時候被執行。
console.log("hhh")
}
}
var p1 = new People();//hhh
用處:實例化一個人的時候必須為他指定一個名字等等。。
//第一種寫法
class People {
name;//聲明瞭一個name屬性
constructor(name:string){//這裡接受實例化傳來的值且設置參數類型
this.name = name;//這裡會訪問上面聲明的name屬性且給他傳入我們接收到的值
};
getName(){
console.log(this.name);
}
}
var p1 = new People("rope");//在這裡實例化的時候給constructor傳入一個值
p1.getName();//rope
//第二種寫法
class People {
constructor(public name:string){//這裡接受實例化傳來的值且設置參數類型
//這個寫法會被People類創建一個name屬性且把傳入的值賦給它。
//構造函數上需要明確的聲明訪問控制符
};
getName(){
//如果構造函數中name沒有聲明訪問控制符,People類裡面也沒有name屬性。
console.log(this.name);//所以這裡是得不到的。
}
}
var p1 = new People("rope");//在這裡實例化的時候給constructor傳入一個值
p1.getName();//rope
類的繼承
1、extends
通過extends關鍵字可以實現繼承
這個時候Student實例化的p1身上也擁有了People的屬性和方法。
在Student類中的屬性和方法People的實例是沒有的。
2、super
第一個用法:調用父類的構造函數
class People {
constructor(public name:string){
//這裡是被下麵的super調用了。
//這個寫法會被People類創建一個name屬性且把傳入的值賦給它。
console.log("People")
};
getName(){
console.log(this.name);
}
}
class Student extends People {
constructor(name: string, public code:string){//實例化一個學生必須有名字和學號
//這個寫法會被Student類創建一個code屬性且把傳入的值賦給它。
super(name);//通過super可以調用父類(People)的構造函數把name傳過去了。
console.log("Student")
}
getCode(){
console.log(this.code);
console.log(this.name)
}
}
var p1 = new Student("huo","18")
p1.getCode()
輸出結果,註意順序:
super調用People的構造函數→Student再執行→p1.getCode()再按順序輸出code和name。
第二個用法:可以調用父類的其他方法
class People {
mifan(){
console.log("吃米飯");
}
}
class Student extends People {
chifan(){
super.mifan();//直接通過super打點就可以調用父類的其他方法。
this.xuexi();
}
private xuexi() {
//這個方法本身是可以這在Student外部調用的,我想讓他必須先吃飯再學習。
//也就是只讓他在Student內部被調用,所以給他設置了訪問控制符。
console.log("吃完米飯學習");
}
}
var p1 = new Student();
p1.chifan();
輸出結果:
2、泛型
參數化的類型,一般來限制集合的內容。
class People {
constructor(public name:string){
};
}
class Student extends People {
constructor(name: string, public code:string){
super(name);
}
}
class Teacher extends People {
constructor(name: string, public code: string) {
super(name);
}
}
var arr: Array<People> = [];//<>中就是規定我這個arr數組只能存放跟People類型一樣的數據
arr[0] = new Student("huo", "18");
arr[1] = new Teacher("huoqingchi", "23");
console.log(arr)
輸出結果:
如果你存放其他類型的數據會有警告:
3、介面
用來建立某種代碼約定,使得其它開發者在調用某個方法或創建新的類時必須遵循介面所定義的代碼約定。
第一中用法:作為一個方法的參數類型的聲明
//使用interface 來聲明一個介面
interface jiekou {//介面的名字就交jiekou
name:string;
age:number;
}
class People{
constructor(public consig: jiekou){//讓介面作為一個方法的參數類型的聲明
}
}
var p1 = new People({
//當你去調用這個方法的時候TypeScript會去檢查你傳過去的參數是否符合介面所約定的格式。
name:"huoqingchi",
age:18
//參數不能多也不能少,如果沒有值可以填null。
})
第二種用法:用介面來聲明方法。
interface People {
chi();//People介面有個吃飯的方法。
}
class Student implements People {
//implements的意思是Student類實現People這個介面
//也就是它必須實現這個介面裡面的方法。
chi(){
console.log("我吃素的");
}
}
class Teacter implements People {
chi(){
console.log("我吃肉的");
}
}
4、模塊
模塊可以幫助開發者將代碼分割為可重用的單元。開發者可以自己決定將模塊中的那些資源(類,方法,變數)暴露出去供外部使用,那些資源只能在模塊內使用,一個文件就是一個模塊。
./demo/ide/tscript/test.ts
export var a = 10;//export是暴露出去的意思。
var b = 20;//沒有暴露出去的就只能在這個模塊中使用。
export function fn1() {
console.log("我是fn1")
}
function fn2() {
console.log("我是fn2")
}
export class CLazz1 {
constructor() {
console.log("我是CLazz1類")
}
}
class CLazz2 {
constructor() {
console.log("我是CLazz2類")
}
}
./demo/ide/tscript/test2.ts
import { a, fn1, CLazz1} from './test';
//import是導入的意思,from是從哪裡導入,{}中是導入那些東西。
console.log(a);
console.log(fn1);
console.log(CLazz1);
//一個模塊中既可以import導入也可以export
export function fn3() {
console.log("我是fn3")
}
輸出結果:
5、註解
註解為程式的元素(類,方法,變數)加上更直觀明瞭的說明,這些說明信息與程式的業務邏輯無關,而是供指定的工具或框架使用的。
import {Component} from '@angular/core';//這裡是用的angular,後續會增加vue,react。
@Component({//這裡就是註解
selector:'app-root',
templaterUrl: './app.component.html',//載入到app.component.html頁面中
styleUrls:['./app.component.css']//載入app.component.css樣式文件
})
export class AppComponent {//當你用angular載入這個類的時候它會執行上面的註解
title = "app works!";
}
app.component.html
<h1>{{title}}</h1><!--頁面會顯示app works!-->
6、類型定義文件(*.d.ts)
類型定義文件用來幫助開發者在TypeScript中使用已有的JavaScript的工具包如:JQuery;
我們使用了typings,npm install -g typings
。
./demo/ide
在項目文件夾下。
打開CMD視窗運行typings install dt~jquery --global
//這裡是jquery舉例,如果需要其它的記得更換。
其中”dt~”為使用DefinitelyTyped類型定義的意思,vscode可以識別這種定義。
沒有安裝之前:
安裝之後:會自動生成typings文件夾
結束語
TypeScript的基礎知識點我們就講完了,後續根據反饋再整理更新。
TypeScript的文檔:http://www.typescriptlang.org/docs/home.html
本人的博客:https://www.cnblogs.com/rope/
本人的github:https://github.com/mufengsm
本人的郵箱:[email protected]
作者:Rope