TypeScript

初識(shí)TypeScript

TypeScript 的介紹

TypeScript是一種由微軟開發(fā)的開源印蔗、跨平臺(tái)的編程語(yǔ)言。它是JavaScript的超集丑勤,最終會(huì)被編譯為JavaScript代碼华嘹。

TypeScript擴(kuò)展了JavaScript的語(yǔ)法,所以任何現(xiàn)有的JavaScript程序可以運(yùn)行在TypeScript環(huán)境中法竞。

TypeScript是為大型應(yīng)用的開發(fā)而設(shè)計(jì)耙厚,并且可以編譯為JavaScript。

TypeScript 是 JavaScript 的一個(gè)超集爪喘,主要提供了類型系統(tǒng)和對(duì) ES6+ 的支持**颜曾,它由 Microsoft 開發(fā),代碼開源于 GitHub 上

TypeScript 主要有3 大特點(diǎn)

始于JavaScript秉剑,歸于JavaScript

TypeScript 可以編譯出純凈泛豪、 簡(jiǎn)潔的 JavaScript 代碼,并且可以運(yùn)行在任何瀏覽器上侦鹏、Node.js 環(huán)境中和任何支持 ECMAScript 3(或更高版本)的JavaScript 引擎中诡曙。

強(qiáng)大的類型系統(tǒng)

類型系統(tǒng)允許 JavaScript 開發(fā)者在開發(fā) JavaScript 應(yīng)用程序時(shí)使用高效的開發(fā)工具和常用操作比如靜態(tài)檢查和代碼重構(gòu)。

先進(jìn)的 JavaScript

TypeScript 提供最新的和不斷發(fā)展的 JavaScript 特性略水,包括那些來(lái)自 2015 年的 ECMAScript 和未來(lái)的提案中的特性价卤,比如異步功能和 Decorators,以幫助建立健壯的組件渊涝。

總結(jié)

TypeScript 在社區(qū)的流行度越來(lái)越高慎璧,它非常適用于一些大型項(xiàng)目,也非常適用于一些基礎(chǔ)庫(kù)跨释,極大地幫助我們提升了開發(fā)效率和體驗(yàn)胸私。

安裝 TypeScript

命令行運(yùn)行如下命令,全局安裝 TypeScript:

npm install -g typescript

安裝完成后鳖谈,在控制臺(tái)運(yùn)行如下命令岁疼,檢查安裝是否成功(3.x):

tsc -V

第一個(gè) TypeScript 程序

編寫 TS 程序

src/hellowrld.ts

function greeter(person) {

? ? return'Hello,'+person

}

let user = 'Yee'

console.log(greeter(user))

手動(dòng)編譯代碼

我們使用了 .ts 擴(kuò)展名,但是這段代碼僅僅是 JavaScript 而已缆娃。

在命令行上(終端)捷绒,運(yùn)行 TypeScript 編譯器:

tsc hellworld.ts

輸出結(jié)果為一個(gè)helloword.js文件。包含了和輸入文件相同的JavaScript代碼

在命令行上贯要,通過(guò) Node.js 運(yùn)行這段代碼:

node helloworld.js

控制臺(tái)輸出:

Hello, Yee

vscode自動(dòng)編譯

1). 生成配置文件tsconfig.json

?? tsc --init

2). 修改tsconfig.json配置

?? "outDir": "./js",

?? "strict": false, ? ?

3). 啟動(dòng)監(jiān)視任務(wù):

?? 終端 -> 運(yùn)行任務(wù) -> 監(jiān)視tsconfig.json

類型注解

? TypeScript 工具帶來(lái)的高級(jí)功能暖侨。 給 person 函數(shù)的參數(shù)添加 : string 類型注解,如下

function greeter (person: string) {

? return 'Hello, ' + person

}

let user = 'Yee'

console.log(greeter(user))

TypeScript 里的類型注解是一種輕量級(jí)的為函數(shù)或變量添加約束的方式崇渗。 在這個(gè)例子里它碎,我們希望 greeter 函數(shù)接收一個(gè)字符串參數(shù)函荣。 然后嘗試把 greeter 的調(diào)用改成傳入一個(gè)數(shù)組

function greeter (person: string) {

? return 'Hello, ' + person

}

let user = [0, 1, 2]

console.log(greeter(user))

重新編譯,你會(huì)看到產(chǎn)生了一個(gè)錯(cuò)誤:

error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.

類似地扳肛,嘗試刪除 greeter 調(diào)用的所有參數(shù)。 TypeScript 會(huì)告訴你使用了非期望個(gè)數(shù)的參數(shù)調(diào)用了這個(gè)函數(shù)乘碑。 在這兩種情況中挖息,TypeScript提供了靜態(tài)的代碼分析,它可以分析代碼結(jié)構(gòu)和提供的類型注解兽肤。

要注意的是盡管有錯(cuò)誤套腹,greeter.js 文件還是被創(chuàng)建了。 就算你的代碼里有錯(cuò)誤资铡,你仍然可以使用 TypeScript电禀。但在這種情況下,TypeScript 會(huì)警告你代碼可能不會(huì)按預(yù)期執(zhí)行笤休。

接口

讓我們繼續(xù)擴(kuò)展這個(gè)示例應(yīng)用尖飞。這里我們使用接口來(lái)描述一個(gè)擁有 firstName 和 lastName 字段的對(duì)象。 在 TypeScript 里店雅,只在兩個(gè)類型內(nèi)部的結(jié)構(gòu)兼容政基,那么這兩個(gè)類型就是兼容的。 這就允許我們?cè)趯?shí)現(xiàn)接口時(shí)候只要保證包含了接口要求的結(jié)構(gòu)就可以闹啦,而不必明確地使用 implements 語(yǔ)句沮明。

interface Person {

? ? firstName:sting

? ? lastName:string

}

function greeter(person:Person) {

? ? return 'Hello,'+person.firstName+' 'person.lastname

}

let user = {

? ? flastName:'Yee',

? ? lastName:'Huang'

}

console.log(greeter(user))

最后,讓我們使用類來(lái)改寫這個(gè)例子窍奋。 TypeScript 支持 JavaScript 的新特性荐健,比如支持基于類的面向?qū)ο缶幊獭?/p>

讓我們創(chuàng)建一個(gè) User 類,它帶有一個(gè)構(gòu)造函數(shù)和一些公共字段琳袄。因?yàn)轭惖淖侄伟私涌谒枰淖侄谓。运麄兡芎芎玫募嫒荨?/p>

還要注意的是,我在類的聲明上會(huì)注明所有的成員變量挚歧,這樣比較一目了然扛稽。

class USer {

? ? fullName:string

? ? fistName:string

? ? lastName:string


? ? constructor(firstName:string,lastName:string) {

? ? ? ? this.firstName = firstName

? ? ? ? this.lastName = lastName

? ? ? ? this.fullName = firstName+' '+lastName

? ? }

}

interface Person {

? firstName:string

? lastName:string

}

function greeter (person:Person) {

? return 'Hello,+ person.firstName + '' + person.lastName

}

let user = new User('Yee','Huang')

console.log(greeter(user))

重新運(yùn)行 tsc greeter.ts 你會(huì)看到TypeScript里的類只是一個(gè)語(yǔ)法糖,本質(zhì)還是JavaScript實(shí)現(xiàn)

使用webpack打包TS

下載依賴

npm install -D typescript

npm install -D webpack webpack-cli

npm install -D webpack-dev-server

npm install -D html-webpack-plugin clean-webpack-plugin

npm install -D ts-loader

npm install cross-env

安裝依賴出現(xiàn)版本過(guò)高問(wèn)題滑负,參考下面鏈接

npm install -D html-webpack-plugin@4.5.0

npm install -D ts-loader@4.4.2

入口JS: src/main.ts

// import './01_helloworld'

document.write('Hello Webpack TS!')

index頁(yè)面: public/index.html

<!DOCTYPE html>

<htmllang="en">

<head>

<metacharset="UTF-8">

<metaname="viewport"content="width=device-width, initial-scale=1.0">

<metahttp-equiv="X-UA-Compatible"content="ie=edge">

<title>webpack&TS</title>

</head>

<body>


</body>

</html>

build/webpack.config.js

const{CleanWebpackPlugin}=require('clean-webpack-plugin')

constHtmlWebpackPlugin=require('html-webpack-plugin')

constpath=require('path')

constisProd=process.env.NODE_ENV==='production'// 是否生產(chǎn)環(huán)境

functionresolve(dir) {

returnpath.resolve(__dirname,'..',dir)

}

module.exports={

mode:isProd?'production':'development',

entry: {

app:'./src/main.ts'

? },

output: {

path:resolve('dist'),

filename:'[name].[contenthash:8].js'

? },

module: {

rules: [

? ?? {

test:/\.tsx?$/,

use:'ts-loader',

include: [resolve('src')]

? ?? }

?? ]

? },

plugins: [

newCleanWebpackPlugin({

?? }),

newHtmlWebpackPlugin({

template:'./public/index.html'

?? })

? ],

resolve: {

extensions: ['.ts','.tsx','.js']

? },

devtool:isProd?'cheap-module-source-map':'cheap-module-eval-source-map',

devServer: {

host:'localhost',// 主機(jī)名

stats:'errors-only',// 打包日志輸出輸出錯(cuò)誤信息

port:8081,

open:true

? },

}

配置打包命令

"dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.js",

"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"

運(yùn)行與打包

yarn dev

yarn build

Typescript常用語(yǔ)法

基礎(chǔ)類型

布爾值

最基本的數(shù)據(jù)類型就是簡(jiǎn)單的 true/false 值在张,在JavaScript 和 TypeScript 里叫做 boolean(其它語(yǔ)言中也一樣)。

//? ? ? : 類型

letisDone:boolean=false;

isDone=true;

數(shù)字

和 JavaScript 一樣矮慕,TypeScript 里的所有數(shù)字都是浮點(diǎn)數(shù)帮匾。 這些浮點(diǎn)數(shù)的類型是 number。 除了支持十進(jìn)制和十六進(jìn)制字面量痴鳄,TypeScript 還支持 ECMAScript 2015中引入的二進(jìn)制和八進(jìn)制字面量瘟斜。

leta1:number=10// 十進(jìn)制

leta2:number=0b1010// 二進(jìn)制

leta3:number=0o12// 八進(jìn)制

leta4:number=0xa// 十六進(jìn)制

字符串

JavaScript 程序的另一項(xiàng)基本操作是處理網(wǎng)頁(yè)或服務(wù)器端的文本數(shù)據(jù)。 像其它語(yǔ)言里一樣,我們使用 string 表示文本數(shù)據(jù)類型螺句。 和 JavaScript 一樣虽惭,可以使用雙引號(hào)(")或單引號(hào)(')表示字符串。

letname:string='tom'

name='jack'

// name = 12 // error

letage:number=12

constinfo=`My name is ${name}, I am ${age}years old!`

總結(jié):ts中變量一開始是什么類型蛇尚,那么后期賦值的時(shí)候就只能用這個(gè)類型芽唇,不允許用其他類型的數(shù)據(jù)賦值給這個(gè)變量如?

let str:string = '你好'//可以

let str:string = 1234 //error

undefined和null

TypeScript 里,undefined 和 null 兩者各自有自己的類型分別叫做 undefined 和 null取劫。 它們的本身的類型用處不是很大:

letu:undefined=undefined

letn:null=null

默認(rèn)情況下 null 和 undefined 是所有類型的子類型匆笤。 就是說(shuō)你可以把 null 和 undefined 賦值給 number 類型的變量。

//需要將tsconfig.json 中的嚴(yán)格模式關(guān)閉

"strict": false,? //是否開啟嚴(yán)格模式?

數(shù)組

TypeScript 像 JavaScript 一樣可以操作數(shù)組元素谱邪。 有兩種方式可以定義數(shù)組炮捧。 第一種,可以在元素類型后面接上[]惦银,表示由此類型元素組成的一個(gè)數(shù)組:

//語(yǔ)法" let 變量名:數(shù)據(jù)類型[] = [值1咆课,值2,值3]

letlist1:number[]=[1,2,3]

第二種方式是使用數(shù)組泛型璧函,Array<元素類型>:

//語(yǔ)法:let 變量名:Array<數(shù)據(jù)類型> = [值1傀蚌,值2,值3]

letlist2:Array<number>=[1,2,3]

數(shù)組定義后蘸吓,里面的數(shù)據(jù)類型必須和定義數(shù)組時(shí)候的類型是一致的善炫,否則error

元組 Tuple

元組類型允許表示一個(gè)已知元素?cái)?shù)量和類型的數(shù)組,各元素的類型不必相同库继。 比如箩艺,你可以定義一對(duì)值分別為 string 和 number 類型的元組。

//在定義數(shù)組的時(shí)候宪萄,類型和數(shù)據(jù)的個(gè)數(shù)一開始就已經(jīng)限定了

lett1: [string,number]

t1=['hello',10]// OK

t1=[10,'hello']// Error

當(dāng)訪問(wèn)一個(gè)已知索引的元素艺谆,會(huì)得到正確的類型:

console.log(t1[0].substring(1))// OK

console.log(t1[1].substring(1))// Error, 'number' 不存在 'substring' 方法

枚舉

enum 類型是對(duì) JavaScript 標(biāo)準(zhǔn)數(shù)據(jù)類型的一個(gè)補(bǔ)充。 使用枚舉類型可以為一組數(shù)值賦予友好的名字拜英。

enumColor{

Red,

Green,

Blue

}

// 枚舉數(shù)值默認(rèn)從0開始依次遞增

// 根據(jù)特定的名稱得到對(duì)應(yīng)的枚舉數(shù)值

letmyColor:Color=Color.Green

console.log(myColor,Color.Red,Color.Blue)// 1 0 2

默認(rèn)情況下静汤,從 0 開始為元素編號(hào)。 你也可以手動(dòng)的指定成員的數(shù)值居凶。 例如虫给,我們將上面的例子改成從 1 開始編號(hào):

enumColor{Red=1,Green,Blue}

letc:Color=Color.Green

或者,全部都采用手動(dòng)賦值:

enumColor{Red=1,Green=2,Blue=4}

letc:Color=Color.Green

枚舉類型提供的一個(gè)便利是你可以由枚舉的值得到它的名字侠碧。 例如抹估,我們知道數(shù)值為 2,但是不確定它映射到 Color 里的哪個(gè)名字弄兜,我們可以查找相應(yīng)的名字:

enumColor{Red=1,Green,Blue}

letcolorName:string=Color[2]

console.log(colorName)// 'Green'

any

有時(shí)候药蜻,我們會(huì)想要為那些在編程階段還不清楚類型的變量指定一個(gè)類型瓷式。 這些值可能來(lái)自于動(dòng)態(tài)的內(nèi)容,比如來(lái)自用戶輸入或第三方代碼庫(kù)语泽。 這種情況下贸典,我們不希望類型檢查器對(duì)這些值進(jìn)行檢查而是直接讓它們通過(guò)編譯階段的檢查。 那么我們可以使用 any 類型來(lái)標(biāo)記這些變量:

letnotSure:any=4

notSure='maybe a string'

notSure=false// 也可以是個(gè) boolean

在對(duì)現(xiàn)有代碼進(jìn)行改寫的時(shí)候踱卵,any 類型是十分有用的瓤漏,它允許你在編譯時(shí)可選擇地包含或移除類型檢查。并且當(dāng)你只知道一部分?jǐn)?shù)據(jù)的類型時(shí)颊埃,any 類型也是有用的。 比如蝶俱,你有一個(gè)數(shù)組班利,它包含了不同的類型的數(shù)據(jù):

letlist:any[]=[1,true,'free']

list[1]=100

void

某種程度上來(lái)說(shuō),void 類型像是與 any 類型相反榨呆,它表示沒(méi)有任何類型罗标。 當(dāng)一個(gè)函數(shù)沒(méi)有返回值時(shí),你通常會(huì)見到其返回值類型是 void:

/* 表示沒(méi)有任何類型, 一般用來(lái)說(shuō)明函數(shù)的返回值不能是undefined和null之外的值 */

functionfn():void{

console.log('fn()')

// return undefined

// return null

// return 1 // error

}

聲明一個(gè) void 類型的變量沒(méi)有什么大用积蜻,因?yàn)槟阒荒転樗x予 undefined 和 null:

letunusable:void=undefined

object

object 表示非原始類型闯割,也就是除 number,string竿拆,boolean之外的類型宙拉。

使用 object 類型,就可以更好的表示像 Object.create 這樣的 API丙笋。例如:

functionfn2(obj:object):object{// 定義的參數(shù)是object類型 返回值也是object類型

console.log('fn2()',obj)

return{}

// return undefined

// return null

}

console.log(fn2(newString('abc')))

// console.log(fn2('abc') // error

console.log(fn2(String))

聯(lián)合類型

聯(lián)合類型(Union Types)表示取值可以為多種類型中的一種需求1: 定義一個(gè)一個(gè)函數(shù)得到一個(gè)數(shù)字或字符串值的字符串形式值

functiontoString2(x:number|string) :string{

returnx.toString()

}

需求2: 定義一個(gè)一個(gè)函數(shù)得到一個(gè)數(shù)字或字符串值的長(zhǎng)度

functiongetLength(x:number|string) {

// return x.length // error

if(x.length) {// error

returnx.length

}else{

returnx.toString().length

? }

}

類型斷言

通過(guò)類型斷言這種方式可以告訴編譯器谢澈,“相信我,我知道自己在干什么”御板。 類型斷言好比其它語(yǔ)言里的類型轉(zhuǎn)換锥忿,但是不進(jìn)行特殊的數(shù)據(jù)檢查和解構(gòu)。 它沒(méi)有運(yùn)行時(shí)的影響怠肋,只是在編譯階段起作用敬鬓。 TypeScript 會(huì)假設(shè)你丧肴,程序員夺谁,已經(jīng)進(jìn)行了必須的檢查。

類型斷言有兩種形式烛愧。 其一是“尖括號(hào)”語(yǔ)法, 另一個(gè)為 as 語(yǔ)法

/*

類型斷言(Type Assertion): 可以用來(lái)手動(dòng)指定一個(gè)值的類型

語(yǔ)法:

?? 方式一: <類型>值

?? 方式二: 值 as 類型? tsx中只能用這種方式

*/

/* 需求: 定義一個(gè)函數(shù)得到一個(gè)字符串或者數(shù)值數(shù)據(jù)的長(zhǎng)度 */

functiongetLength(x:number|string) {

if((<string>x).length) {

return(xasstring).length

}else{

returnx.toString().length

? }

}

console.log(getLength('abcd'),getLength(1234))

類型推斷

類型推斷: TS會(huì)在沒(méi)有明確的指定類型的時(shí)候推測(cè)出一個(gè)類型有下面2種情況: 1. 定義變量時(shí)賦值了, 推斷為對(duì)應(yīng)的類型. 2. 定義變量時(shí)沒(méi)有賦值, 推斷為any類型

/* 定義變量時(shí)賦值了, 推斷為對(duì)應(yīng)的類型 */

letb9=123// number

// b9 = 'abc' // error

/* 定義變量時(shí)沒(méi)有賦值, 推斷為any類型 */

letb10// any類型

b10=123

b10='abc'

接口

接口初探

需求: 創(chuàng)建人的對(duì)象, 需要對(duì)人的屬性進(jìn)行一定的約束

id是number類型, 必須有, 只讀的

name是string類型, 必須有

age是number類型, 必須有

sex是string類型, 可以沒(méi)有

下面通過(guò)一個(gè)簡(jiǎn)單示例來(lái)觀察接口是如何工作的:

/*

在 TypeScript 中酪惭,我們使用接口(Interfaces)來(lái)定義對(duì)象的類型

接口: 是對(duì)象的狀態(tài)(屬性)和行為(方法)的抽象(描述)

接口類型的對(duì)象

?? 多了或者少了屬性是不允許的

?? 可選屬性: ?

?? 只讀屬性: readonly

*/

/*

需求: 創(chuàng)建人的對(duì)象, 需要對(duì)人的屬性進(jìn)行一定的約束

? id是number類型, 必須有, 只讀的

? name是string類型, 必須有

? age是number類型, 必須有

? sex是string類型, 可以沒(méi)有

*/

// 定義人的接口

interfaceIPerson{

id:number

name:string

age:number

sex:string

}

constperson1:IPerson={

id:1,

name:'tom',

age:20,

sex:'男'

}

類型檢查器會(huì)查看對(duì)象內(nèi)部的屬性是否與IPerson接口描述一致, 如果不一致就會(huì)提示類型錯(cuò)誤希痴。

屬性

接口里的屬性不全都是必需的。 有些是只在某些條件下存在春感,或者根本不存在砌创。

interfaceIPerson{

id:number

name:string

age:number

sex?:string

}

帶有可選屬性的接口與普通的接口定義差不多虏缸,只是在可選屬性名字定義的后面加一個(gè) ? 符號(hào)。

可選屬性的好處之一是可以對(duì)可能存在的屬性進(jìn)行預(yù)定義嫩实,好處之二是可以捕獲引用了不存在的屬性時(shí)的錯(cuò)誤刽辙。

constperson2:IPerson={

id:1,

name:'tom',

age:20,

// sex: '男' // 可以沒(méi)有

}

只讀屬性

一些對(duì)象屬性只能在對(duì)象剛剛創(chuàng)建的時(shí)候修改其值。 你可以在屬性名前用 readonly 來(lái)指定只讀屬性:

interfaceIPerson{

readonlyid:number

name:string

age:number

sex?:string

}

一旦賦值后再也不能被改變了甲献。

constperson2:IPerson={

id:2,

name:'tom',

age:20,

// sex: '男' // 可以沒(méi)有

// xxx: 12 // error 沒(méi)有在接口中定義, 不能有

}

person2.id=2// error

readonly vs const

最簡(jiǎn)單判斷該用 readonly 還是 const 的方法是看要把它做為變量使用還是做為一個(gè)屬性宰缤。 做為變量使用的話用 const,若做為屬性則使用 readonly晃洒。

函數(shù)類型

接口能夠描述 JavaScript 中對(duì)象擁有的各種各樣的外形慨灭。 除了描述帶有屬性的普通對(duì)象外,接口也可以描述函數(shù)類型球及。

為了使用接口表示函數(shù)類型氧骤,我們需要給接口定義一個(gè)調(diào)用簽名。它就像是一個(gè)只有參數(shù)列表和返回值類型的函數(shù)定義吃引。參數(shù)列表里的每個(gè)參數(shù)都需要名字和類型筹陵。

/*

接口可以描述函數(shù)類型(參數(shù)的類型與返回的類型)

*/

interfaceSearchFunc{

(source:string,subString:string):boolean

//參數(shù)的類型? ? ? ? ? ? ? ? ? ? ? //返回的值

}

這樣定義后,我們可以像使用其它接口一樣使用這個(gè)函數(shù)類型的接口镊尺。 下例展示了如何創(chuàng)建一個(gè)函數(shù)類型的變量朦佩,并將一個(gè)同類型的函數(shù)賦值給這個(gè)變量。

constmySearch:SearchFunc=function(source:string,sub:string):boolean{

returnsource.search(sub)>-1

}

console.log(mySearch('abcd','bc'))

類類型

類實(shí)現(xiàn)接口

與 C# 或 Java 里接口的基本作用一樣庐氮,TypeScript 也能夠用它來(lái)明確的強(qiáng)制一個(gè)類去符合某種契約语稠。

/*

類類型: 實(shí)現(xiàn)接口

1. 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口

2. 一個(gè)接口可以繼承多個(gè)接口

*/

interfaceAlarm{

alert():any;

}

interfaceLight{

lightOn():void;

lightOff():void;

}

classCarimplementsAlarm{

alert() {

console.log('Car alert');

? }

}

一個(gè)類可以實(shí)現(xiàn)多個(gè)接口

classCar2implementsAlarm,Light{

alert() {

console.log('Car alert');

? }

lightOn() {

console.log('Car light on');

? }

lightOff() {

console.log('Car light off');

? }

}

接口繼承接口

和類一樣,接口也可以相互繼承旭愧。 這讓我們能夠從一個(gè)接口里復(fù)制成員到另一個(gè)接口里颅筋,可以更靈活地將接口分割到可重用的模塊里。

interfaceLightableAlarmextendsAlarm,Light{

}

基本示例

下面看一個(gè)使用類的例子:

/*

類的基本定義與使用

*/

classGreeter{

// 聲明屬性

message:string

// 構(gòu)造方法

constructor(message:string) {

this.message=message

? }

// 一般方法

greet():string{

return'Hello '+this.message

? }

}

// 創(chuàng)建類的實(shí)例

constgreeter=newGreeter('world')

// 調(diào)用實(shí)例的方法

console.log(greeter.greet())

// 1.類 類型:類的類型输枯,類的類型议泵,類的類型可以通過(guò)接口來(lái)實(shí)現(xiàn)

(()=>{

// 定義一個(gè)接口

interfaceIFly{

fly()

? }

//定義一個(gè)類,這個(gè)類就是上面定義的接口桃熄,也可以理解為先口,IFly接口約束了當(dāng)前的這個(gè)Person類

classPersonimplementsIFly{//implement實(shí)現(xiàn)? person 實(shí)現(xiàn) IFly接口

//實(shí)現(xiàn)接口的方法

fly() {

console.log('我會(huì)飛了,我是超人')

? }

}

// 實(shí)例化對(duì)象

constperson=newPerson()

person.fly()

//--------------------------------

//2.定義一個(gè)接口

interfaceISwim{

swim()

}

// 定義一個(gè)類瞳收,這個(gè)類就是IFly和ISwim(當(dāng)前這個(gè)類可以實(shí)現(xiàn)多個(gè)接口碉京,一個(gè)類同時(shí)也可以被多個(gè)接口進(jìn)行約束)

classPerson2implementsIFly,ISwim{

fly(){

console.log('我飛了2')

? }

swim() {

console.log('我游泳2')

? }

}

//實(shí)例化對(duì)象

constperson2=newPerson2

person2.fly()

person2.swim()

// 類可以通過(guò)接口的方式來(lái)定義這個(gè)類的類型

// 類可以實(shí)現(xiàn)一個(gè)接口,也可以實(shí)現(xiàn)多個(gè)接口螟深。要注意接口中內(nèi)容都要真正的是實(shí)現(xiàn)

//--------------------------------

//3.定義了一個(gè)接口谐宙,可以繼承其他的多個(gè)接口

interfaceIMyFlyAndSwimextendsIFly,ISwim{? }

//定義一個(gè)類,直接實(shí)現(xiàn)IMFlyAndSwim這個(gè)接口

classPerson3implementsIMyFlyAndSwim{

fly(){

console.log('我飛了2')

? }

swim() {

console.log('我游泳2')

? }

}

})()

如果你使用過(guò) C# 或 Java界弧,你會(huì)對(duì)這種語(yǔ)法非常熟悉凡蜻。 我們聲明一個(gè) Greeter 類搭综。這個(gè)類有 3 個(gè)成員:一個(gè)叫做 message 的屬性,一個(gè)構(gòu)造函數(shù)和一個(gè) greet 方法划栓。

你會(huì)注意到兑巾,我們?cè)谝萌魏我粋€(gè)類成員的時(shí)候都用了 this。 它表示我們?cè)L問(wèn)的是類的成員忠荞。

后面一行蒋歌,我們使用 new 構(gòu)造了 Greeter 類的一個(gè)實(shí)例。它會(huì)調(diào)用之前定義的構(gòu)造函數(shù)委煤,創(chuàng)建一個(gè) Greeter 類型的新對(duì)象堂油,并執(zhí)行構(gòu)造函數(shù)初始化它。

最后一行通過(guò) greeter 對(duì)象調(diào)用其 greet 方法

//類:可以理解為模板碧绞,通過(guò)模板可以實(shí)例化對(duì)象

//面向?qū)ο蟮木幊趟枷?/p>

(() => {

?? // ts 中類的定義及使用

?? class Person {

? ? ?? // 定義屬性

? ? ?? name:string

? ? ?? age:number

? ? ?? gender:string

? ? ?? // 定義構(gòu)造函數(shù):為了將來(lái)實(shí)例化對(duì)象的時(shí)候称诗,可以直接對(duì)屬性的值進(jìn)行初始化

? ? ?? constructor(name:string='大傻春',age:number=18,gender:string='男'){

? ? ? ? ?? //更新對(duì)象中的屬性數(shù)據(jù)

? ? ? ? ?? this.name = name

? ? ? ? ?? this.age = age

? ? ? ? ?? this.gender = gender

? ? ?? }

? ? ?? // 定義實(shí)例方法

? ? ?? sayHi(str:string){

? ? ? ? ?? console.log(`大家好,我是${this.name},今年${this.age}头遭,性別${this.gender}`,str)

? ? ?? }

?? }

?? //ts中使用類,實(shí)例化對(duì)象癣诱,可以直接進(jìn)行初始化操作

?? const person = new Person('二傻',10,'女')

?? person.sayHi('你是誰(shuí)')

})()

繼承

// 繼承:類與類之間的關(guān)系

// 繼承后類與類之間的叫法:

// A類繼承了B這個(gè)類计维,那么A類叫做子類,B類叫做基類

// 子類:派生類

// 基類:超類(父類)

// 發(fā)生了繼承關(guān)系就出現(xiàn)父子關(guān)系

(() => {

?? // 定義一個(gè)類撕予,作為基類(超類/父類)

?? class Person {

? ? ?? name:string

? ? ?? age:number

? ? ?? gender:string

? ? ?? //定義構(gòu)造函數(shù)

? ? ?? constructor(name:string = '小明',age:number=18,gender:string = '男') {

? ? ? ? ?? //更新屬性數(shù)據(jù)

? ? ? ? ?? this.name = name

? ? ? ? ?? this.age = age

? ? ? ? ?? this.gender = gender

? ? ?? }

? ? ?? //定義實(shí)例方法

? ? ?? sayHi(str:string) {

? ? ? ? ?? console.log(`我是:${this.name},今年${this.age},${this.gender},${str}`)

? ? ?? }

?? }

?? // 定義一個(gè)類鲫惶,繼承自Person

?? class Student extends Person {

? ? ?? constructor(name:string,age:number,gender:string){

? ? ? ? ?? // 調(diào)用的父類的構(gòu)造函數(shù),使用的是super

? ? ? ? ?? super(name,age,gender)//super()訪問(wèn)和調(diào)用一個(gè)對(duì)象父對(duì)象上的函數(shù)

? ? ?? }

? ? ?? //可以調(diào)用父類中的方法

? ? ?? sayHi(){

? ? ? ? ?? console.log('學(xué)生類的sayHi方法')

? ? ? ? ?? super.sayHi('1')

? ? ?? }

?? }

?? // 實(shí)例化Person

?? const person = new Person()

?? person.sayHi('2')

?? //實(shí)例化Student

?? const stu = new Student('3',16,'女')

?? stu.sayHi()

?? // Student先使用extends關(guān)鍵字來(lái)繼承Person類实抡,然后實(shí)例化Student類stu欠母,然后stu方法使用父級(jí)方法sayHi

?? //子類調(diào)用父類的構(gòu)造函數(shù)使用的是super關(guān)鍵字

?? //子類可以重寫父類的方法


})()

多態(tài)

// 多態(tài): 父類型的引用指向了子類型的對(duì)象,不同類型的對(duì)象針對(duì)相同的方法吆寨,產(chǎn)生了不同的行為

(()=>{

// 定義父類

classAnimal{

name:string

//定義一個(gè)構(gòu)造函數(shù)

constructor(name:string){

// 更新數(shù)據(jù)值

this.name=name

? ? ?? }

// 實(shí)例方法

run(distance:number=1){//distance距離

console.log(this.name,`跑了${distance}米`)

? ? ?? }

?? }

//定義子類

classDogextendsAnimal{

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

constructor(name:string){

//調(diào)用父類的構(gòu)造函數(shù)赏淌,實(shí)現(xiàn)子類中屬性的初始化

super(name)

? ? ?? }

//實(shí)例方法

run(distance:number=5){//distance距離

console.log(this.name,`跑了${distance}米`)

? ? ?? }

?? }

//定義子類

classPigextendsAnimal{

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

constructor(name:string){

//調(diào)用父類的構(gòu)造函數(shù),實(shí)現(xiàn)子類中屬性的初始化

super(name)

? ? ?? }

//實(shí)例方法

run(distance:number=10){//distance距離

console.log(this.name,`跑了${distance}米`)

? ? ?? }

?? }

// 實(shí)例化父對(duì)象

constani:Animal=newAnimal('動(dòng)物')

ani.run()

//實(shí)例化子對(duì)象

constdog:Dog=newDog('大黃')

dog.run()

// 實(shí)例化子類對(duì)象

constpig:Pig=newPig('豬豬俠')

pig.run()

// 父類和子類的關(guān)系:父子關(guān)系啄清,此時(shí)六水,父類類型創(chuàng)建子類的對(duì)象

constdog1:Animal=newDog('小黃')

dog1.run()

constpig1:Animal=newPig('小豬豬俠')

pig1.run()

// 該函數(shù)需要的參數(shù)是Animal類型的

functionshowRun(ani:Animal) {

ani.run()

showRun(dog1)

showRun(pig1)

?? }

})()

// 修飾符(類中成員的修飾符):主要是描述類中的成員(屬性,構(gòu)造函數(shù)辣卒,方法)的可訪問(wèn)性

// 類中的成員都有自己的默認(rèn)訪問(wèn)符掷贾,public

// public修飾符---公共的,類中的成員默認(rèn)的修飾符荣茫,代表的是公共的想帅。任何位置都可以訪問(wèn)類中的成員

// private修飾符--- 私有的,類中的成員如果使用private來(lái)修飾啡莉,那么外部是無(wú)法訪問(wèn)這個(gè)成員數(shù)據(jù)的港准,當(dāng)然旨剥,子類也無(wú)法訪問(wèn)該成員數(shù)據(jù)

// protected修飾符,類中的成員使用protected來(lái)修飾叉趣,那么外部無(wú)法訪問(wèn)這個(gè)成員的數(shù)據(jù)泞边,子類卻可以訪問(wèn)。

(()=>{

//定義一個(gè)類

classPerson{

// public name:string

// private name:string

protectedname:string

?? }

})()

讀取器 get set

(()=>{

classPerson{

firstName:string

lastName:string

constructor(firstName:string,lastName:string){

this.firstName=firstName

this.lastName=lastName

? ? ?? }

//讀取器

getfullName() {

console.log

returnthis.firstName+'_'+this.fullName

? ? ?? }

//修改器

setfullName(aaa) {

letnames=aaa.split('_')

this.firstName=names[0]

this.lastName=names[1]

? ? ?? }

?? }

constperson:Person=newPerson('西門','吹雪')

console.log(person)

person.fullName='南宮_問(wèn)天'

console.log(person.fullName)

})()


靜態(tài)成員(靜態(tài)屬性/靜態(tài)方法)

// 靜態(tài)成員: 在類中通過(guò)static修飾的屬性或者方法疗杉,那么就是靜態(tài)的屬性及靜態(tài)的方法阵谚,也稱為靜態(tài)成員

// 靜態(tài)成員在使用的時(shí)候是通過(guò)類名.的語(yǔ)法來(lái)調(diào)用的

(()=>{

classPerson{

// 靜態(tài)屬性

// 類中默認(rèn)有一個(gè)內(nèi)置的name屬性

staticname1:string='123'


// 構(gòu)造函數(shù)是不能通過(guò)static來(lái)進(jìn)行修飾的

//static constructor(){} error

// 靜態(tài)屬性

staticsayHi(){

console.log('321')

? ? ?? }

?? }

//const person:Person =new Person('456')

// 通過(guò)類名.靜態(tài)方法來(lái)調(diào)用內(nèi)部的靜態(tài)方法

Person.sayHi()

// 通過(guò)類名.靜態(tài)屬性來(lái)訪問(wèn)成員數(shù)據(jù)

console.log(Person.name1)

// 通過(guò)類名. 靜態(tài)方法的方式來(lái)設(shè)置成員數(shù)據(jù)

Person.name1='999'

console.log(Person.name1)

})()

抽象類

// 抽象類:包含抽象方法(抽象方法一般沒(méi)有任何的具體內(nèi)容的實(shí)現(xiàn)),

//也可以包含實(shí)例方法烟具,抽象類是不能被實(shí)例化的梢什,為了讓子類進(jìn)行實(shí)例化及實(shí)現(xiàn)內(nèi)部的抽象方法

(()=>{

// 定義一個(gè)抽象類

abstractclassAnimal{

//抽象方法

abstracteat()// 抽象方法不能有具體的實(shí)現(xiàn)

//實(shí)例方法

sayHi(){

console.log('吃')

? ? ? }

? }

// 抽象類的對(duì)象是無(wú)法實(shí)例化的

//const ani:Animal = new Animal ? /error

//定義一個(gè)子類()派生類

classDogextendsAnimal{

eat(){

console.log('飛著吃')

? ?? }

? }

})()

// 總結(jié)感受,有點(diǎn)像接口朝聋,先把子類的各項(xiàng)類似的方法抽象出來(lái)嗡午,在父類中抽象方法

函數(shù)

// 函數(shù):一些被頻繁使用的代碼封裝起來(lái)。在需要的時(shí)候直接調(diào)用即可

(()=>{

// // js寫法

// // 函數(shù)聲明冀痕,命名函數(shù)

// function add(x,y){

// ? ? return x + y

// }

// //函數(shù)表達(dá)式荔睹,匿名函數(shù)

// const add2 = function (x,y){

// ? ? return x + y

// }

//-----------------------------------

// ts寫法

// 函數(shù)聲明,命名函數(shù)

functionadd(x:string,y:string):string{

//括弧內(nèi)參數(shù)的:string指的是傳入的x是string類型括弧外的:string是指函數(shù)的返回值是string

returnx+y

?? }

//函數(shù)表達(dá)式言蛇,匿名函數(shù)

constadd2=function(x:number,y:number):number{

returnx+y

?? }


//ts函數(shù)的完整寫法

//函數(shù)本身類型中的 => 和 es6 沒(méi)關(guān)系僻他,是 ts 中關(guān)于定義函數(shù)本身類型的語(yǔ)法

//add3--->變量名--->函數(shù)add3

//(x:number,y:number) => number 當(dāng)前這個(gè)函數(shù)的類型 =>在這里不是箭頭函數(shù),是定義函數(shù)的類型

//function (x:number,y:number):number {return x+y} 就相當(dāng)于符合上面函數(shù)的值

constadd3:(x:number,y:number)=>number=function(x:number,y:number) :number{

returnx+y

?? }

constas=add3(10,20)

console.log(as)

})()

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

// 可選參數(shù):函數(shù)在聲明的時(shí)候腊尚,內(nèi)部的參數(shù)使用了吨拗?進(jìn)行了修飾,那么就表示該參數(shù)可以傳入也可以不傳入

// 默認(rèn)參數(shù):函數(shù)在聲明的時(shí)候內(nèi)部的參數(shù)有自己的默認(rèn)值婿斥,此時(shí)的這個(gè)參數(shù)就可以叫做默認(rèn)參數(shù)劝篷。

(()=>{

constgetFullName=function(firstName:string='東方',lastName?:string):string{

if(lastName){

returnfirstName+'_'+lastName

}else{

returnfirstName

? ? ?? }

?? }

// 函數(shù)調(diào)用

// 什么也不傳入

console.log(getFullName())

// 只傳入姓氏

console.log(getFullName('諸葛'))

//傳入姓氏和名字

console.log(getFullName('諸葛','亮'))

})()

剩余參數(shù)

// 剩余參數(shù)(rest參數(shù))

// 剩余參數(shù)是放在函數(shù)聲明的時(shí)候所有的參數(shù)的最后

(()=>{

// ...args:string[]---->剩余的參數(shù),放在了一個(gè)字符串的數(shù)組中民宿,args里面

functionshowMsg(str:string,...args:string[]){

console.log(str)//a

console.log(args)//b c d e

?? }

showMsg('a','b','c','b')

})()

函數(shù)重載

// 函數(shù)重載:函數(shù)的名字不同娇妓,函數(shù)的參數(shù)及個(gè)數(shù)不同

(()=>{

// 定義一個(gè)函數(shù)

//函數(shù)重載聲明

functionadd(x:string,y:string):string

functionadd(x:number,y:number):number

// 函數(shù)聲明

functionadd(x:string|number,y:string|number):string|number{

if(typeofx==='string'&&typeofy==='string') {

returnx+y

}elseif(typeofx==='number'&&typeofy==='number') {

returnx+y

? ? ?? }

?? }

// 函數(shù)調(diào)用

console.log(add('諸葛','孔明'))

// 兩個(gè)參數(shù)都是數(shù)字

console.log(add(10,20))

//函數(shù)重載應(yīng)用, 傳入的是非法的數(shù)據(jù)活鹰,ts給出提出錯(cuò)誤信息的內(nèi)容峡蟋,報(bào)紅色。

console.log(add('諸葛',12))

console.log(add(23,'孔明'))

})()

泛型

泛型

// 泛型:在定義函數(shù)华望、接口蕊蝗、類的時(shí)候、不能預(yù)先確定要使用的數(shù)據(jù)的類型赖舟,而是在使用函數(shù)蓬戚、接口、類的時(shí)候才能確定數(shù)據(jù)的類型

// 使用方法:<>

(()=>{

?? function getArr4<T>(value:T,count:number):T[]{

? ? ?? // <T> T 類似形參宾抓,根據(jù)需要定

? ? ?? const arr :Array<T> = []

? ? ?? for (let i= 0;i< count;i++){

? ? ? ? ?? arr.push(value)

? ? ?? }

? ? ?? return arr

?? }

?? const arr1 = getArr4<number>(200.1234,5)

?? //在使用的使用子漩,<>里面的規(guī)定數(shù)據(jù)類型

?? const arr2 = getArr4<string>('abcdefg',5)

?? console.log(arr1)

?? console.log(arr1[0].toFixed(3))

?? console.log(arr2[0].split(''))


})()

多個(gè)泛型參數(shù)

(()=>{

?? // 多個(gè)泛型參數(shù)的函數(shù):函數(shù)中有多個(gè)泛型的參數(shù)

?? function getMsg<K,V>(value1:K,value2:V):[K,V] {

? ? ?? return [value1,value2]

?? }

?? const arr1 = getMsg<string,number>('jack',100.2345)

?? console.log(arr1[0].split(''))

?? console.log(arr1[1].toFixed(1))

})()

泛型接口

//泛型接口:在定義接口時(shí)豫喧,為接口中的屬性或者方法定義泛型類型,在使用接口的時(shí)候再具體指定具體的泛型接口

(()=>{

// 定義一個(gè)泛型的接口

interfaceIBaseCRUD<T>{

data:Array<T>

add: (t:T)=>T

getUserId: (id:number)=>T

?? }

// 定義了用戶信息的類

classUser{

id?:number

name:string

age:number

constructor(name:string,age:number) {

this.name=name

this.age=age

? ? ?? }

?? }

//再定義一個(gè)增刪改查操作的類

//CRUD----create,read,update,delete

classUserCRUDimplementsIBaseCRUD<User>{

data:Array<User>=[]

add(user:User):User{

user.id=Date.now()+Math.random()

this.data.push(user)

returnuser

}//儲(chǔ)存用戶信息

getUserId(id:number):User{

returnthis.data.find(user=>user.id===id)

? ? ?? }

//根據(jù)id查找用戶信息對(duì)象

?? }

//實(shí)例化添加用戶信息對(duì)象的類UserCRUD

constuserCRUD=newUserCRUD()

userCRUD.add(newUser('jack',20))

userCRUD.add(newUser('bob',18))

const{id}=userCRUD.add(newUser('tom',22))

constuser=userCRUD.getUserId(id)

console.log(userCRUD.data)

console.log(user)

})()

泛型類

(()=>{

// 定義一個(gè)類幢泼,類中的屬性值的類型是不確定的紧显,方法中的參數(shù)和返回值的類型也是不確定

// 定義一個(gè)泛型類

classGenericNumber<T>{

//默認(rèn)的屬性的值是泛型類型

defaultValue:T

//函數(shù)本身類型中的 => 和 es6 沒(méi)關(guān)系,是 ts 中關(guān)于定義函數(shù)本身類型的語(yǔ)法

add:(x:T,y:T)=>T

?? }

//在實(shí)例化類的對(duì)象時(shí)候缕棵,再確定泛型的類型

constg1:GenericNumber<number>=newGenericNumber<number>()

// 設(shè)置屬性值

g1.defaultValue=100

// 相加的方法

g1.add=function(x,y) {

returnx+y

?? }


})()

泛型約束

(()=>{

?? //如果直接對(duì)一個(gè)泛型參數(shù)取length屬性孵班,會(huì)error,因?yàn)榉盒筒恢浪羞@個(gè)屬性

?? // 定義一個(gè)接口招驴,用于約束將來(lái)的莫個(gè)類型中必需的length屬性

?? interface ILength{

? ? ?? // 接口中有一個(gè)屬性:length

? ? ?? length:number

?? }


?? function getLength<T extends ILength>(x:T):number{

? ? ?? return x.length

?? }

?? console.log(getLength<string>('afsdfdsafsad'))

?? console.log(getLength<number>(1234))// 因?yàn)閚umber沒(méi)有l(wèi)ength篙程,所有不滿足約束,error

})()

其他

當(dāng)使用第三方庫(kù)時(shí)别厘,我們需要引用它的聲明文件虱饿,才能獲得對(duì)應(yīng)的代碼補(bǔ)全、接口提示等功能

很多的第三方庫(kù)都定義了對(duì)應(yīng)的聲明文件庫(kù), 庫(kù)文件名一般為 @types/xxx, 可以在

https://www.npmjs.com/package/package 進(jìn)行搜索

有的第三庫(kù)在下載時(shí)就會(huì)自動(dòng)下載對(duì)應(yīng)的聲明文件庫(kù)(比如: webpack),有的可能需要單獨(dú)下載(比如jQuery/react)

例如:下載jQuery聲明文件: npm install @types/jquery --save-dev

什么是聲明語(yǔ)句

假如我們想使用第三方庫(kù) jQuery触趴,一種常見的方式是在 html 中通過(guò) ` 標(biāo)簽引入jQuery氮发,然后就可以使用全局變量$或jQuery` 了。

但是在 ts 中冗懦,編譯器并不知道 $ 或 jQuery 是什么東西

/*

當(dāng)使用第三方庫(kù)時(shí)折柠,我們需要引用它的聲明文件,才能獲得對(duì)應(yīng)的代碼補(bǔ)全批狐、接口提示等功能。

聲明語(yǔ)句: 如果需要ts對(duì)新的語(yǔ)法進(jìn)行檢查, 需要要加載了對(duì)應(yīng)的類型說(shuō)明代碼

? declare var jQuery: (selector: string) => any;

聲明文件: 把聲明語(yǔ)句放到一個(gè)單獨(dú)的文件(jQuery.d.ts)中, ts會(huì)自動(dòng)解析到項(xiàng)目中所有聲明文件

下載聲明文件: npm install @types/jquery --save-dev

*/

jQuery('#foo');

// ERROR: Cannot find name 'jQuery'.

這時(shí)前塔,我們需要使用 declare var 來(lái)定義它的類型

declarevarjQuery: (selector:string)=>any;

jQuery('#foo');

declare var 并沒(méi)有真的定義一個(gè)變量嚣艇,只是定義了全局變量 jQuery 的類型,僅僅會(huì)用于編譯時(shí)的檢查华弓,在編譯結(jié)果中會(huì)被刪除食零。它編譯結(jié)果是:

jQuery('#foo');

一般聲明文件都會(huì)單獨(dú)寫成一個(gè) xxx.d.ts 文件

創(chuàng)建 01_jQuery.d.ts, 將聲明語(yǔ)句定義其中, TS編譯器會(huì)掃描并加載項(xiàng)目中所有的TS聲明文件

declarevarjQuery: (selector:string)=>any;

內(nèi)置對(duì)象

JavaScript 中有很多內(nèi)置對(duì)象,它們可以直接在 TypeScript 中當(dāng)做定義好了的類型寂屏。

內(nèi)置對(duì)象是指根據(jù)標(biāo)準(zhǔn)在全局作用域(Global)上存在的對(duì)象贰谣。這里的標(biāo)準(zhǔn)是指 ECMAScript 和其他環(huán)境(比如 DOM)的標(biāo)準(zhǔn)。

ECMAScript 的內(nèi)置對(duì)象

BooleanNumberStringDateRegExpError

/* 1. ECMAScript 的內(nèi)置對(duì)象 */

letb:Boolean=newBoolean(1)

letn:Number=newNumber(true)

lets:String=newString('abc')

letd:Date=newDate()

letr:RegExp=/^1/

lete:Error=newError('error message')

b=true

// let bb: boolean = new Boolean(2)? // error

BOM 和 DOM 的內(nèi)置對(duì)象

WindowDocumentHTMLElementDocumentFragmentEventNodeList

constdiv:HTMLElement=document.getElementById('test')

constdivs:NodeList=document.querySelectorAll('div')

document.addEventListener('click', (event:MouseEvent)=>{

console.dir(event.target)

})

constfragment:DocumentFragment=document.createDocumentFragment()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迁霎,一起剝皮案震驚了整個(gè)濱河市吱抚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌考廉,老刑警劉巖秘豹,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昌粤,居然都是意外死亡既绕,警方通過(guò)查閱死者的電腦和手機(jī)啄刹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凄贩,“玉大人誓军,你說(shuō)我怎么就攤上這事∑T” “怎么了昵时?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)评肆。 經(jīng)常有香客問(wèn)我债查,道長(zhǎng),這世上最難降的妖魔是什么瓜挽? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任盹廷,我火速辦了婚禮,結(jié)果婚禮上久橙,老公的妹妹穿的比我還像新娘俄占。我一直安慰自己,他們只是感情好淆衷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布缸榄。 她就那樣靜靜地躺著,像睡著了一般祝拯。 火紅的嫁衣襯著肌膚如雪甚带。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天佳头,我揣著相機(jī)與錄音鹰贵,去河邊找鬼。 笑死康嘉,一個(gè)胖子當(dāng)著我的面吹牛碉输,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亭珍,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼敷钾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了肄梨?” 一聲冷哼從身側(cè)響起阻荒,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎众羡,沒(méi)想到半個(gè)月后财松,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年辆毡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了菜秦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舶掖,死狀恐怖球昨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情眨攘,我是刑警寧澤主慰,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站鲫售,受9級(jí)特大地震影響共螺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜情竹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一藐不、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秦效,春花似錦雏蛮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苔货,卻和暖如春犀概,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夜惭。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工姻灶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人滥嘴。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像至耻,于是被迫代替她去往敵國(guó)和親若皱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • TypeScript 什么是TypeScript TypeScript就是所謂JavaScript的超集尘颓,Type...
    無(wú)聊寫寫閱讀 204評(píng)論 0 0
  • #### TypeScript 基于JavaScript之上的語(yǔ)言 解決了JavaScript類型系統(tǒng)的問(wèn)題 - ...
    爵跡01閱讀 288評(píng)論 0 1
  • Stack Overflow 在 90,000 名開發(fā)者中開展了一項(xiàng)調(diào)查[https://link.zhihu.c...
    路條編程閱讀 980評(píng)論 0 0
  • 一.TypeScript基礎(chǔ)類型 booleanconst flag: boolean = false numbe...
    Joemoninni閱讀 570評(píng)論 0 4
  • 一走触、TS簡(jiǎn)介 1.支持所有的js的語(yǔ)法 2.安裝:yarn global add typscript npm i...
    Snyu_L閱讀 556評(píng)論 0 1