typescript入門和typescript面向?qū)ο笕腴T

前言

typescript(以下簡稱ts)是微軟開發(fā)、google(Angular2)支持的 js超集(增加面向?qū)ο缶幊痰奶匦院湍承〦S6語法特性),任何js都可以不經(jīng)修改的在ts環(huán)境下運(yùn)行。很多著名的項(xiàng)目都已經(jīng)將ts作為了開發(fā)語言,例如,我國的HTML5游戲引擎Egret、我國的前端樣式庫Ant-desgin等。總之,ts絕對(duì)代表了未來的大前端語言趨勢(shì),不學(xué)就落后了。

ts環(huán)境開發(fā)

一般情況下,可以在babel或者ts的在線練習(xí)環(huán)境來快速體驗(yàn)ts語言。但是,為了做項(xiàng)目,還是需要在本地安裝好開發(fā)環(huán)境的,接下來,我們就看看如何在本地配置開發(fā)環(huán)境和IDE的。

安裝compiler

npm i -g typescript
tsc --version
// 新建一個(gè)test.ts文件
export class testTS {

}
tsc test.ts --->編譯--->test.js

"use strict";
exports.__esModule = true;
var testTS = /** @class */ (function () {
    function testTS() {
    }
    return testTS;
}());
exports.testTS = testTS;

與vscode進(jìn)行集成

tsc --init // 創(chuàng)建tsconfig.json

有了tsconfig.json文件后,就可以對(duì)文件進(jìn)行配置,設(shè)置好js文件夾和ts文件夾。

編譯ts文件

使用vscode編譯ts文件非常的方便,只需要run task即可。

run task

run task后會(huì)出現(xiàn)tsc:build 、tsc:watch兩個(gè)選項(xiàng),tsc:build是快速編譯,tsc:watch是實(shí)時(shí)、監(jiān)控編譯,編譯好后,文件就會(huì)存在于在tsconfig.json指定好的目錄下了。

前端工程比較龐大的時(shí)候,或者需要將多個(gè)ts輸出到多個(gè)js文件夾下的時(shí)候,建議使用webpack、gulp或者grunt來進(jìn)行項(xiàng)目的打包和編譯。這幾個(gè)工具都是前端工程化的工具,在此不做一一展開來講了。

簡單學(xué)學(xué)ts語法

ts語法很多也是es6語法,因此,簡單說說一些ts語法,全當(dāng)對(duì)es6進(jìn)行復(fù)習(xí)了。

字符串特性

多行字符串

使用``

字符串模板

使用`${xxx}`

自動(dòng)拆分字符串

下圖,test函數(shù)可以通過字符串模板來調(diào)用參數(shù),就是后邊的這些,可以用字符串模板調(diào)用,然后,自動(dòng)拆分


自動(dòng)拆分字符串之函數(shù)調(diào)用
自動(dòng)拆分字符串之結(jié)果展示

參數(shù)

指定參數(shù)類型

使用【冒號(hào) = :】來指定變量、參數(shù)、函數(shù)返回值類型,并且,類型具有推斷機(jī)制,如果給string類型的變量,賦值數(shù)字的話,IDE會(huì)報(bào)錯(cuò)。(這里也僅僅是IDE會(huì)報(bào)錯(cuò),因此,js是動(dòng)態(tài)語言,不存在類型的概念,通過ts轉(zhuǎn)換為js不管怎么說都是對(duì)的)

另外,通過類的概念自定類型后,自定義的類型也可以作為普通類型使用

var nymm:string='11111dssasd'
var nymm:any='11111dssasd'
var nymm:number='11111dssasd'
var nymm:boolean='11111dssasd'

// 可選參數(shù),b就是可選參數(shù),可以不傳遞
function test(er:string,ki:string = "ddd",op?:string):void{

}

// 自定義類型

class Car {
    name:string;
    logo:string
}

var ben:Car = new Car();

默認(rèn)參數(shù)與可選參數(shù)

給參數(shù)賦默認(rèn)值,如果有普通參數(shù),那么,默認(rèn)參數(shù)不可以為第一個(gè)參數(shù),否則,在賦值的時(shí)候,會(huì)對(duì)參數(shù)的賦值進(jìn)行覆蓋。同時(shí),還提供了【問號(hào) = ?】來指定其為可選參數(shù),并且,可選參數(shù)必須放在必選參數(shù)之后。

function test(er:string,ki:string = "ddd",op?:string):void{

}

函數(shù)

Rest and Spread操作符

Rest and Spread操作符,例如【...args】,這個(gè)操作符表示可以聲明任意數(shù)量的方法參數(shù)。這個(gè)參數(shù)表示的是一個(gè)數(shù)組,調(diào)用該參數(shù)的時(shí)候,要按照數(shù)字的方式進(jìn)行處理。

// 任意長度參數(shù)定義
function fun(...args){}

// 定長參數(shù)定義
function fun2(a,b,c)
var ays = [1,2,9]

// 定長函數(shù)調(diào)用
fun2(...ays)

generator和async函數(shù)操縱順序程序

generator以及async函數(shù),都是promise的語法糖。用來控制函數(shù)的執(zhí)行過程,通過yield和await來控制代碼的執(zhí)行。配合著next(),來控制順序程序的暫停和開啟。然后,每次,調(diào)用next(),都會(huì)停在某一個(gè)yield或者async。

圖片.png

對(duì)于異步函數(shù),其實(shí)就是promise的返回,因此,直接操作返回的對(duì)象即可。

析構(gòu)表達(dá)式(destructuring)

通過表達(dá)式將對(duì)象或數(shù)組拆解成任意數(shù)量的變量

拆解對(duì)象

拆解對(duì)象

拆解數(shù)組

拆解數(shù)組跳過數(shù)據(jù)
拆解數(shù)組 + Rest and Spread操作符

箭頭表達(dá)式

用來聲明匿名函數(shù),消除傳統(tǒng)匿名函數(shù)的this指針問題,因?yàn)?,js中的this關(guān)鍵字,會(huì)發(fā)生js指向和預(yù)期指向不一致的情況。因?yàn)?,this的指向是調(diào)用自己的函數(shù)的指向,但是,因?yàn)殚]包、函數(shù)嵌套調(diào)用等原因,this的指向會(huì)發(fā)生改變。通過箭頭表達(dá)式,將this指向了最外層的函數(shù),從而,讓一個(gè)函數(shù)內(nèi)共享了this內(nèi)存,從而解決指向改變的問題。

最簡單的匿名函數(shù)

var kill = (bill,kate)=>bill + kate;

等價(jià)于

var kill = function (bill,kate) {return bill + kate};

this指向發(fā)生改變的一種情況

例如,上圖的情況,this指向了匿名函數(shù),因此會(huì)打印不出值。

this指向發(fā)生改變的一種情況的實(shí)際數(shù)據(jù)打印

對(duì)于非箭頭函數(shù)表達(dá)式下的this的簡單說明

在普通函數(shù)中,this指代的是調(diào)用他的函數(shù),例如

var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};

var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

這個(gè)函數(shù)打印的就不是一個(gè)值,因?yàn)?,foo是引用,因此是全局環(huán)境下的對(duì)象對(duì)于this的調(diào)用,因此,值是不一樣的。

當(dāng)然,關(guān)于this,很有必要單獨(dú)開一個(gè)文章來講解

循環(huán)

本節(jié)將要講解forEach()、for in、for of循環(huán)的異同

forEach()

forEach(),有兩個(gè)特性,第一是不能break跳出,第二是會(huì)忽略對(duì)象的展示。

forEach()
忽略對(duì)象的展示

for in

for in循環(huán)的是keys,同時(shí)可以使用break跳出。

for of

for of循環(huán)的是values,同時(shí)可以使用break跳出。

面向?qū)ο?/h1>

ts的面向?qū)ο?,或者說js的面向?qū)ο笈cc++或者java很不一樣。因?yàn)檫@種解釋型的語言,本身就已經(jīng)是對(duì)象了,因此,在操縱內(nèi)存的時(shí)候要格外小心。

Class

ts要求使用面向?qū)ο蟮奶匦詠頃鴮懗绦?,既然是面向?qū)ο螅敲?,就可以更好的利用繼承、封裝和多態(tài)了。使用面向?qū)ο?,可以更好的?shí)現(xiàn)抽象定義和整個(gè)程序的架構(gòu)。

定義

類的定義

我們可以看到es5下,類的定義是基于匿名函數(shù)和閉包的,同時(shí)還提供了prototype這個(gè)屬性。在此不做展開,大家自行查閱資料。(此處涉及到匿名函數(shù)的調(diào)用和原型鏈的知識(shí),此處建議學(xué)習(xí)v8引擎的相關(guān)說明資料https://v8.dev/docs和ECMAScript的說明文檔https://tc39.es/ecma262/#sec-ecmascript-specification-types

另外,對(duì)于上邊的代碼,特別要注意的是,在es5下,匿名函數(shù)一定要自執(zhí)行后,才能調(diào)用,因?yàn)?,在沒有執(zhí)行前,匿名函數(shù)沒有意義。

訪問控制符

默認(rèn)的訪問控制符是public,同時(shí)還可以添加private和protected。public表示都可以訪問,private表示內(nèi)部訪問,protected表示內(nèi)部包或者子類可以訪問。

構(gòu)造函數(shù)(constructor())

構(gòu)造函數(shù)

構(gòu)造函數(shù)的參數(shù),一定要顯式的做訪問控制符的聲明,否則需要在外部單獨(dú)指定其訪問控制權(quán)限。

繼承(extends和super)

如果我們用es5來實(shí)現(xiàn)class和extends語法糖的話,那么就應(yīng)該是這樣的幾個(gè)函數(shù),此處又涉及到多個(gè)問題,因此,之后會(huì)專門開個(gè)文章系列來討論這部分內(nèi)容。另外,通過查看es5的實(shí)現(xiàn)方式,我們也明白了,extends和super的意義。

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    }
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Animal = /** @class */ (function () {
    function Animal(name) {
        this.name = name;
    }
    Animal.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 0; }
        console.log(this.name + " moved " + distanceInMeters + "m.");
    };
    return Animal;
}());
var Snake = /** @class */ (function (_super) {
    __extends(Snake, _super);
    function Snake(name) {
        return _super.call(this, name) || this;
    }
    Snake.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 5; }
        console.log("Slithering...");
        _super.prototype.move.call(this, distanceInMeters);
    };
    return Snake;
}(Animal));
var Horse = /** @class */ (function (_super) {
    __extends(Horse, _super);
    function Horse(name) {
        return _super.call(this, name) || this;
    }
    Horse.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 45; }
        console.log("Galloping...");
        _super.prototype.move.call(this, distanceInMeters);
    };
    return Horse;
}(Animal));
var sam = new Snake("Sammy the Python");
var tom = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);

泛型(generic)

參數(shù)化的類型,一般用來限制集合的內(nèi)容。換句話說,就是聲明某個(gè)集合必須是什么數(shù)據(jù)類型。

var workers:Array<Worker>  = []

這個(gè)數(shù)組就要求,我們只能將worker放到數(shù)組中。

接口(interface)

用來建立某種代碼約定,使得其他開發(fā)者在調(diào)用某個(gè)方法或者創(chuàng)建新的類時(shí)必須遵循接口所定義的代碼約定。使用interface定義,使用implements引用。

定義接口并使用

定義接口并使用

基于implements實(shí)現(xiàn)接口

基于implements實(shí)現(xiàn)接口

模塊(Module)

在ts或者js中,一個(gè)文件,其實(shí)就是一個(gè)模塊,通過export和import進(jìn)行模塊的導(dǎo)出和導(dǎo)入。

模塊可以幫助開發(fā)者將代碼分割為可重用的單元。開發(fā)者可以自己決定將模塊中的哪些資源(類、方法、變量)暴露出去供外部使用,哪些資源只在模塊內(nèi)部使用。

值得注意的是,對(duì)于繼承來說,因?yàn)?,類肯定也是在不同模塊中的,因此,我們既要將模塊import,還要extends對(duì)應(yīng)的類。(此處要注意CommonJS(CMD、AMD)和es6模塊的異同)

注解(annotation)

注解為程序的元素(類、方法、變量)加上更加直觀的說明,這些說明信息與程序的業(yè)務(wù)邏輯無關(guān),只是供指定的工具或者框架使用。(關(guān)于注解,可以具體查看相關(guān)工具的文檔)

類型定義文件(*.d.ts)

ts想要使用js工具包已有的程序應(yīng)該怎么辦呢?之前以及說過了,js可以不經(jīng)修改的在ts下執(zhí)行,那么,我們其實(shí)可以直接調(diào)用js,但是,又存在語法差異,不免會(huì)產(chǎn)生bug,因此,使用類型定義文件來幫助ts調(diào)用js的已有代碼,放在bug的產(chǎn)生。例如:koa等

類型定義文件,來源于DefinitelyTyped項(xiàng)目https://github.com/DefinitelyTyped/DefinitelyTyped

例如koa的類型定義文件就是在這個(gè)下邊https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/koa/index.d.ts,通過 npm i @types/koa便可以安裝這個(gè)項(xiàng)目,也可以通過typings來安裝和查找。這個(gè)項(xiàng)目中,有大量的已有js項(xiàng)目的類型定義文件。

注意,其實(shí)還可以通過通過typings(https://github.com/typings/typings)來尋找以及存在的類型定義文件。但是,由于官方推薦 NPM @types的形式來安裝類型定義文件,因此,可以不去安裝typings了,直接使用npm的安裝方式即可。

npm WARN deprecated typings@2.1.1: Typings is deprecated in favor of NPM @types -- see README for more information
npm WARN deprecated popsicle-proxy-agent@3.0.0: Use `agent` option with `popsicle` directly

npm i typings -g
typings search --name project_name
typings install project_name --save

后記

本文概要的講解了ts和ts的面向?qū)ο?,?duì)于很多知識(shí)都沒有展開來講,例如,es5為什么要那樣構(gòu)建類,class、extends等語法糖的es5版本為啥要那樣寫,注解如何使用等等。

對(duì)于此部分的內(nèi)容,我將會(huì)在后續(xù)的專題中,深入討論的。

討論一下ts做后端開發(fā)

對(duì)于使用過Java、PHP、C#等開發(fā)后端的程序員來說,ts語法會(huì)讓你們感到更加的親切。但是,因?yàn)?,ts本身還在發(fā)展,因此,例如裝飾器、注解等還是需要第三方庫進(jìn)行支持。

Routing-controllers庫

https://github.com/typestack/routing-controllers

該庫為express、koa添加了裝飾器模式,可以通過注解的方式來操控web服務(wù)器。

TypeDI依賴注入庫

https://github.com/pleerock/typedi

TypeORM

https://github.com/typeorm/typeorm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容