TypeScript入門
gitHub:http://www.liu12fei08fei.top/blog/10typescript.html
- TypeScript入門
- 課程內容介紹
- 課程介紹-前置知識
- TypeScript的優勢
- 搭建TypeScript開發環境
- 什麽是compiler?為什麽需要compiler?
- 使用在線compiler開發
- 搭建本地TypeScript開發環境
- TypeScript-字符串新特性(所有例子都是es6語法)
- TypeScript-參數新特性
- 參數類型
- 默認參數
- 可選參數
- 函數新特性
- Rest and Spread操作符(...):用來聲明任意數量的方法參數,即rest參數
- generator函數:控制函數的執行過程,手工暫停和恢復代碼執行
- destructuring析構表達式:通過表達式將對象或數組拆解成任意數量的變量
- 表達式和循環
- 箭頭表達式:用來聲明匿名函數,消除傳統匿名函數的this指針問題
- forEach()、for in和for of
- forEach:
- for in
- for of
- 面向對象特性
- 類(class):TypeScript的核心,使用TypeScript開發時,大部分代碼都是寫在類裏面的。
- 類的定義
- 返回控制符
- 類的構造函數,即:constructor方法
- 類的繼承:兩個關鍵字
- extends,獲得繼承類中所有屬性和方法
- super
- 調用父類的構造函數
- 用來調用父類的方法
- 面向對象特性
- 泛型-generic:是指參數化的類型,一般用來限制集合的內容
- 接口-Interface:用來建立某種代碼約定,使得其它開發者在調用某個方法或創建新的類時必須遵循接口所定義的代碼約定
- 模塊-module:模塊可以幫助開發者將代碼分割為可重用的單元。開發者可以自己決定將模塊中的哪些資源(類、方法、變量)暴露出去供外部使用,哪些資源只在模塊內使用。
- 註解-annotation:註解為程序的元素(類、方法、變量)加上更直觀更明了的說明,這些說明信息與程序的業務邏輯無關,而是供指定的工具或框架使用的
- 類型定義文件(*.d.ts):類型定義文件用來幫助開發者在TypeScript中使用已有的JS的工具包;如:jQuery、zepto等
- 微軟開發一門編程語言
- JavaScript的超集
- 遵循ES6腳本語言規範
- TypeScript擴展了JavaScript的語法,任何已經存在的JS程序,可以不加任何改動的在TypeScript環境下運行
- TypeScript只是向JS中添加一些新的,遵循ES6規範的語法,以及基於類的面向對象編程的這種特性
- 其次,2016年9月底發布的Angular2框架,這個框架本身是由TypeScript語言本身來編寫的
- TypeScript這門語言是由Microsoft(微軟)和Google(谷歌),在背後支持
- 因此,TypeScript有可能稱為前端腳本語言發展的一個主流方向
課程內容介紹
- 學習TypeScript的好處
- 安裝TypeScript開發環境
- TypeScript概念、語法和特性介紹
課程介紹-前置知識
- 理解ES5、ES6、JavaScript、TypeScript的概念和關系
- ES是客戶端腳本語言的規範,ES5、ES6是不同的版本
- JavaScript和TypeScript是兩種客戶端腳本語言
- JavaScript是實現了ES5規範,TypeScript實現了ES6規範
- 有基礎的JavaScript開發經驗
TypeScript的優勢
- 支持ES6規範
- 強大的IDE支持
- Angular2的開發語言
搭建TypeScript開發環境
- 就是安裝TypeScript compiler
什麽是compiler?為什麽需要compiler?
- 它是編譯器,編譯器的作用就是把TypeScript代碼轉化成JS代碼
- 因為主流瀏覽器沒有完全支持ES6,需要轉化成ES5
使用在線compiler開發
搭建本地TypeScript開發環境
TypeScript-字符串新特性(所有例子都是es6語法)
一、 多行字符串
var str = `111,
222,
333,
444`;
- 多行字符串使用雙撇號聲明變量(即:反引號),好處是可以隨意換行無需拼接字符串
二、 字符串模板:在多行字符串裏,用一個表達式去插入變量或者用以調用方法
var myName = ‘怪誕咖啡‘;
var getName = function () {
return myName;
}
console.log(`Hello ${myName}`); // 調用變量
console.log(`Hello ${getName()}`); // 調用函數
- 註:字符串模板${},只有在反引號``中有作用,在雙引號("")和單引號(‘‘)中只會當字符串輸出
三、 自動拆分字符串:當用一個字符串模板去調用一個方法的時候,這個字符串模板裏面表達式的值會自動賦值給被調用方法中的參數
function test(name, age, job) {
console.log(name);
console.log(age);
console.log(job);
}
var myName = "怪誕咖啡";
var getAge = function () {
return 18;
}
test`Hello my name is ${myName}, I‘m ${getAge()}`;
- 調用test函數,進行參數傳遞時候,不需要寫雙括號,直接使用反引號
- 第一個參數是:字符串模板的值 => ["Hello my name is ",", I‘m ",""]
- 第二個參數是:第一個表達式的值 => 怪誕咖啡
- 第三個參數是:第二個表達式的值 => 18
TypeScript-參數新特性
參數類型
一、 在參數名稱後面使用冒號來指定參數的類型
var myName: string = ‘怪誕咖啡‘;
myName = 13;
- 註:報錯只會在typescript環境下,在編譯後的es5環境下是不會報錯的
二、 類型推斷機制,就是當第一次給變量賦值,此變量的類型就固定為第一次賦值的類型
var myName = ‘怪誕咖啡‘;
myName = 13;
- 註:報錯只會在typescript環境下,在編譯後的es5環境下是不會報錯的
三、 要想在typescript環境下任意賦值,就需要賦值為:any
var myName:any = ‘怪誕咖啡‘;
myName = 13;
四、 其他基本類型
- 數值類型 var num: number = 20;
- 布爾類型 var boo: boolean = true;
- void類型:void不是用來聲明變量的,而是用來聲明變量的返回值的
void類型例子:
function test(): void{
return ‘‘; // 報錯
}
function test(): string{
return ‘‘; // 不報錯
}
五、 除了給變量和函數聲明類型外,還可以給參數聲明類型
function test(name: string, age) {
return name;
}
test(1); // 報錯,只能使用string類型進行調用
註:介紹了如何聲明類型、typescript類型推斷機制、五種基本的類型、可以聲明類型的位置
六、 自定義類型:在typescript裏面,可以通過class或接口來申明自定義類型
class Person{
name: string;
age: number;
}
var feifei: Person = new Person();
feifei.name = ‘怪誕咖啡‘;
feifei.age = 18;
- 當我們寫feifei.的時候會提示Person有name和age兩個屬性
默認參數
在參數聲明後面用等號來指定參數的默認值
function test(a: string, b: string, c: string) {
console.log(a);
console.log(b);
console.log(c);
}
test(‘1‘,‘2‘,‘3‘); // 必須傳遞三個string類型的參數,否則提示錯誤
給參數指定默認值之後,可以不傳遞參數
function test(a: string, b: string, c: string=‘攻城獅‘) {
console.log(a);
console.log(b);
console.log(c);
}
test(‘1‘, ‘2‘); // 只傳遞兩個參數,第三個參數使用默認值
- 默認值的設定應該遵循從右向左一次設定,否則無法起到合理的作用
可選參數
在方法的參數聲明後面用問號來標明此參數為可選參數
function test(a: string, b?: string, c: string=‘攻城獅‘) {
console.log(a);
console.log(b);
console.log(c);
}
test(‘1‘); // 只傳遞一個參數,第二個參數為undefined,第三個參數為默認值
註意幾點:
- b設置為可選參數,要處理可選參數沒傳的情況
function test(a: string, b?: string, c: string=‘攻城獅‘) {
console.log(a);
console.log(b.length);
console.log(c);
}
說明:b參數為可選參數,在不傳遞參數值的情況下是不允許調用undefined的length屬性的
- 和默認值一樣,可選參數不能聲明在必選參數的後面的
function test(a?: string, b: string, c: string=‘攻城獅‘) {
console.log(a);
console.log(b);
console.log(c);
}
說明:我給a設置為可選參數,b為必選參數,會直接報錯;和設置默認值是一樣的,不允許在必選參數前面設置默認值
函數新特性
Rest and Spread操作符(...):用來聲明任意數量的方法參數,即rest參數
function fun(...args) {
args.forEach(function (arg) {
console.log(arg);
});
}
fun(1, 2, 3);
console.log(‘******‘); // 分隔符
fun(10,8,18,49,100,7)
一個Rest and Spread操作符,反方向使用的方法--目前版本2.6不支持
- 設置傳遞固定數量的參數,在使用的時候傳遞不定數量的參數
function fun(a, b, c) {
console.log(a);
console.log(b);
console.log(c);
}
var args = [1, 2];
fun(...args); // 在typescript中報錯,在轉化的es5中支持,返回值為:1 2 undefined
console.log(‘*****‘);
var args2 = [7, 8, 9, 10, 12];
fun(...args2); // 在typescript中報錯,在轉化的es5中支持,返回值為:7 8 9
generator函數:控制函數的執行過程,手工暫停和恢復代碼執行
- 在es5中,調用一個方法的時候,沒有辦法在函數執行到一半的時候,進行暫停執行
- 在es6中,新加一個關鍵字yield,這個關鍵字可以實現方法暫停執行;yield就好像給代碼加上了斷點一樣,可以通過編程的手段,控制代碼走到某個點暫停執行,然後調用特定方法的時候在進行,可以往復循環
聲明一個generator函數,只要在function後面添加一個即可:`function fun(){}`
function* fun(){
console.log(‘start‘);
yield;
console.log(‘finish‘);
}
// fun(); // 這樣調用generator是不起作用的,必須使用下面的方式調用
var fn = fun();
fn.next(); // 打印start
fn.next(); // 打印finish
destructuring析構表達式:通過表達式將對象或數組拆解成任意數量的變量
- 從對象中通過析構表達式獲得相應屬性和方法,對象析構是用{}大括號聲明
function a() {
return {
myName: ‘怪誕咖啡‘,
age: {
age1: 18,
age2:80
}
}
}
var { myName, age: { age1, age2 } } = a(); // 析構表達式,包括嵌套屬性
var { myName:newName, age: { age1, age2 } } = a(); // 析構表達式,給myName起一個新的名字newName
console.log(age1);
console.log(age2);
解析:返回值,即return返回值,的結構和我們的析構表達式的結構{ myName, age: { age1, age2 } }一一對應,所以析構表達式,即可理解為,解析結構獲得對象屬性的方法
- 從數組中通過析構表達式獲得相應屬性和方法,數組析構是用[]方括號聲明
var arr = [1, 2, 3, 4];
var [num1, num2, ...other] = arr; // 獲取第一個和第二個,其余變量賦值給other
var [,,num3,num4] = arr; // 獲取第三和第四個值
析構表達式好處:當你需要從一個對象的屬性或者是數組的元素裏面,用其中的值賦值給其余變量的時候,可以讓我們寫更少的代碼
表達式和循環
箭頭表達式:用來聲明匿名函數,消除傳統匿名函數的this指針問題
// 無參數表達式
var sum = () => {}
// 只有一個參數的表達式
var sum = arg => {}
// 單行表達式
var sum = (arg1, arg2) => arg1 + arg2;
// 多行表達式
var sum2 = (arg1, arg2) => {
return arg1 + arg2;
}
實際例子:
var arr = [1, 2, 3, 4, 5];
var flt = arr.filter(val => val % 2 == 0);
console.log(flt);
箭頭函數的優勢:
- 簡化書寫
- 最大的優勢,消除了js裏,this關鍵字的問題
- this指向問題
function fn(myName: string) {
this.myName = myName;
setInterval(function () {
console.log(‘myName is:‘+this.myName);
},1000);
}
var myName = 1; // 全局myName,後面的this指向了全局,而不是a
var a = new fn(‘怪誕咖啡‘);
- 改用箭頭函數,消除this指向問題
function fn(myName: string) {
this.myName = myName;
setInterval(() => {
console.log(‘myName is:‘+this.myName);
},1000);
}
var myName = 1;
var a = new fn(‘怪誕咖啡‘); // 消除指向問題
forEach()、for in和for of
forEach:
var arr = [1, 2, 3, 4];
arr.desc = ‘I am number type!‘; // 這行在typescript裏面會報錯
arr.forEach(val => console.log(val));
問題:
- forEach會把desc屬性忽略掉
- foeEach裏面無法打斷循環,break不支持
for in
var arr = [11, 22, 33, 44];
arr.desc = ‘I am number type!‘;
for (var item in arr) {
console.log(item); // key=> 1,2,3,4,desc
console.log(arr[item]); //value=>11,22,33,44,I am number type!
}
問題:
- 不光把數組裏面的值循環出來,同樣會把定義的屬性也循環出來;結果很可能不是我們希望的樣子
for of
- 和forEach差不錯,循環的是你對象或數組的值,而不是像for in循環的key
- for of和forEach的差別是,可以用break可以打斷循環
var arr = [11, 22, 33, 44];
arr.desc = ‘I am number type!‘;
for (var item of arr) {
console.log(item); // key=> 11,22,33,44
}
面向對象特性
類(class):TypeScript的核心,使用TypeScript開發時,大部分代碼都是寫在類裏面的。
- 這裏會介紹類的定義,構造函數,以及類的繼承
類的定義
- 使用class關鍵字聲明類
class Person{
}
- 可以指定類的屬性和方法,一個完整的類具有屬性和方法
class Person{
name;
eat() {
console.log(‘I am eating!‘);
}
}
- 實例化:可以把類理解成為一個模子;所謂實例化,就是根據模子做出實際的產品出來
class Person{
name;
eat() {
console.log(‘I am eating!‘);
}
}
var p1 = new Person();
p1.name = ‘Hello‘;
p1.eat();
var p2 = new Person();
p2.name = ‘World‘;
p2.eat();
返回控制符
- 在聲明類的屬性和方法的時候,可以為其指定一個返回控制符
- 返回控制符的作用是控制類的屬性和方法是否可以在外部被訪問到
- 返回控制符有三個:
- public共用,默認public
- private私有,只有在類的內部才能被訪問到,在外部訪問不到
- protected受保護的,可以在類的內部和子類(繼承)裏面可以被訪問到,在外部訪問不到
類的構造函數,即:constructor方法
- 實際上是類裏面一個特殊的方法,這個方法只有在類被實例化的時候才會被調用
- 而且只會調用一次
- 外部無法訪問到constructor構造函數的
class Person{
constructor() {
console.log(‘構造函數‘)
};
name=‘默認值‘;
eat() {
console.log(‘I am eating!‘);
}
}
var p1 = new Person();
p1.name = ‘Hello‘;
p1.eat();
var p2 = new Person();
p2.name = ‘World‘;
p2.eat();
構造函數的作用:可以在實例化的時候,指定相應屬性
class Person{
constructor(public name:string) {
};
eat() {
console.log(this.name);
}
}
var p1 = new Person(‘Hello‘);
p1.eat();
var p2 = new Person(‘World‘);
p2.eat();
註意:構造函數裏面,定義屬性,要使用控制符來明確聲明,即:public name:any;如果是name:any這樣,說明沒有聲明該屬性,下面無法訪問到
類的繼承:兩個關鍵字
- 一個是extends,用來聲明類的繼承關系
- 另一個是super,用來調用父類的構造函數和方法
extends,獲得繼承類中所有屬性和方法
class Person{
constructor(public name:string) {
};
eat() {
console.log(this.name);
}
}
class Employee extends Person{
// 定義新的屬性和方法
code: string;
work() {
}
}
let em = new Employee(‘coffee‘);
em.eat();
super
調用父類的構造函數
class Person{
constructor(public name:string) {
console.log(‘父類構造函數‘);
};
eat() {
console.log(this.name);
}
}
class Employee extends Person{
constructor(name: string, code: string) {
// 必須調用父類的構造函數,這是硬性規定
super(name);
console.log(‘子類構造函數‘);
this.code = code;
};
code: string;
work() {
}
}
let em = new Employee(‘coffee‘,‘8‘);
em.eat();
用來調用父類的方法
class Person{
constructor(public name:string) {
console.log(‘父類構造函數‘);
};
eat() {
console.log(this.name);
}
}
class Employee extends Person{
constructor(name: string, code: string) {
// 必須調用父類的構造函數,這是硬性規定
super(name);
console.log(‘子類構造函數‘);
this.code = code;
};
code: string;
work() {
// 調用父類的方法
super.eat();
};
// 返回控制符
private doWork() {
}
}
let em = new Employee(‘coffee‘,‘8‘);
em.work();
面向對象特性
泛型-generic:是指參數化的類型,一般用來限制集合的內容
class Person{
constructor(public name:string) {
console.log(‘父類構造函數‘);
};
eat() {
console.log(this.name);
}
}
class Employee extends Person{
constructor(name: string, code: string) {
// 必須調用父類的構造函數,這是硬性規定
super(name);
console.log(‘子類構造函數‘);
this.code = code;
};
code: string;
work() {
// 調用父類的方法
super.eat();
};
private doWork() {
}
}
var workers: Array<Person> = [];
workers[0] = new Person(‘神經了‘);
workers[1] = new Employee(‘神經了‘, ‘8‘);
workers[2] = 3; // 報錯,指定放Person類型的數據
接口-Interface:用來建立某種代碼約定,使得其它開發者在調用某個方法或創建新的類時必須遵循接口所定義的代碼約定
interface IPerson{
name: string;
age: number;
}
class Person{
constructor(public config:IPerson){}
}
// 聲明屬性
var p1 = new Person({
name: ‘coffee‘,
age:8
});
console.log(p1);
實現對應的接口中的方法:
interface Animal{
eat();
}
class Sheep implements Animal{
eat() {
console.log(‘I eat grass‘);
}
}
class Tiger implements Animal{
eat() {
console.log(‘I eat meat‘);
}
}
模塊-module:模塊可以幫助開發者將代碼分割為可重用的單元。開發者可以自己決定將模塊中的哪些資源(類、方法、變量)暴露出去供外部使用,哪些資源只在模塊內使用。
- 模塊在typescript裏面就是一個文件,一個文件就是一個模塊
- 在模塊內部有兩個關鍵字來支撐模塊的特性,export暴露接口、import
// 文件a
import {newName} from "./b"; // 引入b文件,使用b文件中提供的接口newName
// a文件對外提供接口
export var prop1;
var prop2;
export function func1(){
}
function func2(){
}
export class Class1{
}
class Class2{
}
// 獲得b文件提供的接口
console.log(newName);
// b文件
import {Class1, func1, prop1} from "./a"; // 引入a文件
// 獲取a文件提供的接口
console.log(prop1);
func1();
new Class1{
}
// 對外提供接口
export var newName;
註解-annotation:註解為程序的元素(類、方法、變量)加上更直觀更明了的說明,這些說明信息與程序的業務邏輯無關,而是供指定的工具或框架使用的
類型定義文件(*.d.ts):類型定義文件用來幫助開發者在TypeScript中使用已有的JS的工具包;如:jQuery、zepto等
如何找到類型定義文件,肯定不能自己一個個的寫;使用tyings來快速啟動
TypeScript入門