TypeScript類類型:高效使用類型化的面向?qū)ο缶幊汤?/h1>

本文介紹TypeScript集面向?qū)ο蟪橄蟾合⒎庋b、多態(tài)三要素為一體的編程利器,類類型吹由。

在JavaScript(ES5)中僅支持通過(guò)函數(shù)和原型鏈繼承模擬類的實(shí)現(xiàn)(用于抽象業(yè)務(wù)模型、組織數(shù)據(jù)結(jié)構(gòu)并創(chuàng)建可重用組件)朱嘴,自 ES6 引入 class 關(guān)鍵字后倾鲫,它才開始支持使用與Java類似的語(yǔ)法定義聲明類。

TypeScript 作為 JavaScript 的超集萍嬉,自然也支持 class 的全部特性乌昔,并且還可以對(duì)類的屬性、方法等進(jìn)行靜態(tài)類型檢測(cè)壤追。

在實(shí)際業(yè)務(wù)中玫荣,任何實(shí)體都可以被抽象為一個(gè)使用類表達(dá)的類似對(duì)象的數(shù)據(jù)結(jié)構(gòu),且這個(gè)數(shù)據(jù)結(jié)構(gòu)既包含屬性大诸,又包含方法捅厂,比如我們?cè)谙路匠橄罅艘粋€(gè)狗的類贯卦。

class Dog {

?name: string;

?constructor(name: string) {

? ?this.name = name;

? }

?bark() {

? ?console.log('Woof! Woof!');

? }

}

const dog = new Dog('Q');

dog.bark(); // => 'Woof! Woof!'

首先,我們定義了一個(gè) class Dog 焙贷,它擁有 string 類型的 name 屬性撵割、bark 方法和一個(gè)構(gòu)造器函數(shù)。然后辙芍,我們通過(guò) new 關(guān)鍵字創(chuàng)建了一個(gè) Dog 的實(shí)例啡彬,并把實(shí)例賦值給變量 dog。最后故硅,我們通過(guò)實(shí)例調(diào)用了類中定義的 bark 方法庶灿。

如果使用傳統(tǒng)的 JavaScript 代碼定義類,我們需要使用函數(shù)+原型鏈的形式進(jìn)行模擬吃衅,如下代碼所示:

function Dog(name: string) {

?this.name = name; // ts(2683) 'this' implicitly has type 'any' because it does not have a type annotation.

}

Dog.prototype.bark = function () {

?console.log('Woof! Woof!');

};

const dog = new Dog('Q'); // ts(7009) 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.

dog.bark(); // => 'Woof! Woof!'

在第 1~ 3 行往踢,我們定義了 Dog 類的構(gòu)造函數(shù),并在構(gòu)造函數(shù)內(nèi)部定義了 name 屬性徘层,再在第 4 行通過(guò) Dog 的原型鏈添加 bark 方法峻呕。

和通過(guò) class 方式定義類相比,這種方式明顯麻煩不少趣效,而且還缺少靜態(tài)類型檢測(cè)瘦癌。因此,類是 TypeScript 編程中十分有用且不得不掌握的工具跷敬。

下面我們看一下關(guān)于類最主要的特性——繼承讯私,也是面向?qū)ο缶幊倘笠刂弧?/p>

繼承

在 TypeScript 中,使用 extends 關(guān)鍵字就能很方便地定義類繼承的抽象模式西傀,如下代碼所示:

class Animal {

?type = 'Animal';

?say(name: string) {

? ?console.log(`I'm ${name}!`);

? }

}

class Dog extends Animal {

?bark() {

? ?console.log('Woof! Woof!');

? }

}

const dog = new Dog();

dog.bark(); // => 'Woof! Woof!'

dog.say('Q'); // => I'm Q!

dog.type; // => Animal

上面的例子展示了類最基本的繼承用法斤寇。比如第 8 ~12 行定義的Dog是派生類,它派生自第 1~6 行定義的Animal基類池凄,此時(shí)Dog實(shí)例繼承了基類Animal的屬性和方法抡驼。因此,在第 15~17 行我們可以看到肿仑,實(shí)例 dog 支持 bark致盟、say、type 等屬性和方法尤慰。

說(shuō)明:派生類通常被稱作子類馏锡,基類也被稱作超類(或者父類)。

細(xì)心的你可能發(fā)現(xiàn)了伟端,這里的 Dog 基類與第一個(gè)例子中的類相比杯道,少了一個(gè)構(gòu)造函數(shù)。這是因?yàn)?b>派生類如果包含一個(gè)構(gòu)造函數(shù)责蝠,則必須在構(gòu)造函數(shù)中調(diào)用 super() 方法党巾,這是 TypeScript 強(qiáng)制執(zhí)行的一條重要規(guī)則萎庭。

如下示例,因?yàn)榈?1~10 行定義的 Dog 類構(gòu)造函數(shù)中沒(méi)有調(diào)用 super 方法齿拂,所以提示了一個(gè) ts(2377) 的錯(cuò)誤驳规;而第 12~22 行定義的 Dog 類構(gòu)造函數(shù)中添加了 super 方法調(diào)用,所以可以通過(guò)類型檢測(cè)署海。

class Dog extends Animal {

?name: string;

?constructor(name: string) { // ts(2377) Constructors for derived classes must contain a 'super' call.

? ?this.name = name;

? }

?bark() {

? ?console.log('Woof! Woof!');

? }

}

class Dog extends Animal {

?name: string;

?constructor(name: string) {

? ?super(); // 添加 super 方法

? ?this.name = name;

? }

?bark() {

? ?console.log('Woof! Woof!');

? }

}

有些同學(xué)可能會(huì)好奇吗购,這里的 super() 是什么作用?其實(shí)這里的 super 函數(shù)會(huì)調(diào)用基類的構(gòu)造函數(shù)砸狞,如下代碼所示:

class Animal {

?weight: number;

?type = 'Animal';

?constructor(weight: number) {

? ?this.weight = weight;

? }

?say(name: string) {

? ?console.log(`I'm ${name}!`);

? }

}

class Dog extends Animal {

?name: string;

?constructor(name: string) {

? ?super(); // ts(2554) Expected 1 arguments, but got 0.

? ?this.name = name;

? }

?bark() {

? ?console.log('Woof! Woof!');

? }

}

將鼠標(biāo)放到第 15 行 Dog 類構(gòu)造函數(shù)調(diào)用的 super 函數(shù)上捻勉,我們可以看到一個(gè)提示,它的類型是基類 Animal 的構(gòu)造函數(shù):constructor Animal(weight: number): Animal 刀森。并且因?yàn)?Animal 類的構(gòu)造函數(shù)要求必須傳入一個(gè)數(shù)字類型的 weight 參數(shù)踱启,而第 15 行實(shí)際入?yún)榭眨蕴崾玖艘粋€(gè) ts(2554) 的錯(cuò)誤撒强;如果我們顯式地給 super 函數(shù)傳入一個(gè) number 類型的值禽捆,比如說(shuō) super(20)笙什,則不會(huì)再提示錯(cuò)誤了飘哨。

公共、私有與受保護(hù)的修飾符

類屬性和方法除了可以通過(guò) extends 被繼承之外琐凭,還可以通過(guò)修飾符控制可訪問(wèn)性芽隆。

在 TypeScript 中就支持 3 種訪問(wèn)修飾符,分別是 public统屈、private胚吁、protected。

·public 修飾的是在任何地方可見愁憔、公有的屬性或方法腕扶;

·private 修飾的是僅在同一類中可見、私有的屬性或方法吨掌;

·protected 修飾的是僅在類自身及子類中可見半抱、受保護(hù)的屬性或方法。

在之前的代碼中膜宋,示例類并沒(méi)有用到可見性修飾符窿侈,在缺省情況下,類的屬性或方法默認(rèn)都是 public秋茫。如果想讓有些屬性對(duì)外不可見史简,那么我們可以使用private進(jìn)行設(shè)置,如下所示:

class Son {

?public firstName: string;

?private lastName: string = 'Stark';

?constructor(firstName: string) {

? ?this.firstName = firstName;

? ? this.lastName; // ok

? }

}

const son = new Son('Tony');

console.log(son.firstName); //? => "Tony"

son.firstName = 'Jack';

console.log(son.firstName); //? => "Jack"

console.log(son.lastName); // ts(2341) Property 'lastName' is private and only accessible within class 'Son'.

在上面的例子中我們可以看到肛著,第 3 行 Son 類的 lastName 屬性是私有的圆兵,只在 Son 類中可見跺讯;第 2 行定義的 firstName 屬性是公有的,在任何地方都可見殉农。因此抬吟,我們既可以通過(guò)第 10 行創(chuàng)建的 Son 類的實(shí)例 son 獲取或設(shè)置公共的 firstName 的屬性(如第 11 行所示),還可以操作更改 firstName 的值(如第 12 行所示)统抬。

不過(guò)火本,對(duì)于 private 修飾的私有屬性,只可以在類的內(nèi)部可見聪建。比如第 6 行钙畔,私有屬性 lastName 僅在 Son 類中可見,如果其他地方獲取了 lastName 金麸,TypeScript 就會(huì)提示一個(gè) ts(2341) 的錯(cuò)誤(如第 14 行)擎析。

注意:TypeScript 中定義類的私有屬性僅僅代表靜態(tài)類型檢測(cè)層面的私有。如果我們強(qiáng)制忽略 TypeScript 類型的檢查錯(cuò)誤挥下,轉(zhuǎn)譯且運(yùn)行 JavaScript 時(shí)依舊可以獲取到 lastName 屬性揍魂,這是因?yàn)?JavaScript 并不支持真正意義上的私有屬性。

目前棚瘟,JavaScript 類支持 private 修飾符的提案已經(jīng)到 stage 3 了现斋。相信在不久的將來(lái),私有屬性在類型檢測(cè)和運(yùn)行階段都可以被限制為僅在類的內(nèi)部可見偎蘸。如果你感興趣的話庄蹋,可以在proposal-private-methods中進(jìn)行查看。

接下來(lái)我們?cè)倏匆幌率鼙Wo(hù)的屬性和方法迷雪,如下代碼所示:

class Son {

?public firstName: string;

?protected lastName: string = 'Stark';

?constructor(firstName: string) {

? ?this.firstName = firstName;

? ? this.lastName; // ok

? }

}

class GrandSon extends Son {

?constructor(firstName: string) {

? ?super(firstName);

? }

?public getMyLastName() {

? ?return this.lastName;

? }

}

const grandSon = new GrandSon('Tony');

console.log(grandSon.getMyLastName()); // => "Stark"

grandSon.lastName; // ts(2445) Property 'lastName' is protected and only accessible within class 'Son' and its subclasses.

在第 3 行限书,修改 Son 類的 lastName 屬性可見修飾符為 protected,表明此屬性在 Son 類及其子類中可見章咧。如示例第 6 行和第 16 行所示倦西,我們既可以在父類 Son 的構(gòu)造器中獲取 lastName 屬性值,又可以在繼承自 Son 的子類 GrandSon 的 getMyLastName 方法獲取 lastName 屬性的值赁严。

需要注意:雖然我們不能通過(guò)派生類的實(shí)例訪問(wèn)protected修飾的屬性和方法扰柠,但是可以通過(guò)派生類的實(shí)例方法進(jìn)行訪問(wèn)。比如示例中的第 21 行误澳,通過(guò)實(shí)例的 getMyLastName 方法獲取受保護(hù)的屬性 lastName 是 ok 的耻矮,而第 22 行通過(guò)實(shí)例直接獲取受保護(hù)的屬性 lastName 則提示了一個(gè) ts(2445) 的錯(cuò)誤。

只讀修飾符

在前面的例子中忆谓,Son 類 public 修飾的屬性既公開可見裆装,又可以更改值,如果我們不希望類的屬性被更改,則可以使用 readonly 只讀修飾符聲明類的屬性哨免,如下代碼所示:

class Son {

? public readonly firstName: string;

? constructor(firstName: string) {

? ? this.firstName = firstName;

? }

}

const son = new Son('Tony');

son.firstName = 'Jack'; // ts(2540) Cannot assign to 'firstName' because it is a read-only property.

在第 2 行茎活,我們給公開可見屬性 firstName 指定了只讀修飾符,這個(gè)時(shí)候如果再更改 firstName 屬性的值琢唾,TypeScript 就會(huì)提示一個(gè) ts(2540) 的錯(cuò)誤(參見第 9 行)载荔。這是因?yàn)橹蛔x屬性修飾符保證了該屬性只能被讀取,而不能被修改采桃。

注意:如果只讀修飾符和可見性修飾符同時(shí)出現(xiàn)懒熙,我們需要將只讀修飾符寫在可見修飾符后面。

存取器

除了上邊提到的修飾符之外普办,在 TypeScript 中還可以通過(guò)getter工扎、setter截取對(duì)類成員的讀寫訪問(wèn)。

通過(guò)對(duì)類屬性訪問(wèn)的截取衔蹲,我們可以實(shí)現(xiàn)一些特定的訪問(wèn)控制邏輯肢娘。下面我們把之前的示例改造一下,如下代碼所示:

class Son {

? public firstName: string;

? protected lastName: string = 'Stark';

? constructor(firstName: string) {

? ? this.firstName = firstName;

? }

}

class GrandSon extends Son {

? constructor(firstName: string) {

? ? super(firstName);

? }

? get myLastName() {

? ? return this.lastName;

? }

? set myLastName(name: string) {

? ? if (this.firstName === 'Tony') {

? ? ? this.lastName = name;

? ? } else {

? ? ? console.error('Unable to change myLastName');

? ? }

? }

}

const grandSon = new GrandSon('Tony');

console.log(grandSon.myLastName); // => "Stark"

grandSon.myLastName = 'Rogers';

console.log(grandSon.myLastName); // => "Rogers"

const grandSon1 = new GrandSon('Tony1');

grandSon1.myLastName = 'Rogers'; // => "Unable to change myLastName"

在第 14~24 行舆驶,我們使用 myLastName 的getter橱健、setter重寫了之前的 GrandSon 類的方法,在 getter 中實(shí)際返回的是 lastName 屬性沙廉。然后拘荡,在 setter 中,我們限定僅當(dāng) lastName 屬性值為 'Tony' 蓝仲,才把入?yún)?name 賦值給它俱病,否則打印錯(cuò)誤官疲。

在第 28 行中袱结,我們可以像訪問(wèn)類屬性一樣訪問(wèn)getter,同時(shí)也可以像更改屬性值一樣給setter賦值途凫,并執(zhí)行一些自定義邏輯垢夹。

在第 27 行,因?yàn)?grandSon 實(shí)例的 lastName 屬性被初始化成了 'Tony'维费,所以在第 29 行我們可以把 'Rogers' 賦值給 setter 果元。而 grandSon1 實(shí)例的 lastName 屬性在第 32 行被初始化為 'Tony1',所以在第 33 行把 'Rogers' 賦值給 setter 時(shí)犀盟,打印了我們自定義的錯(cuò)誤信息而晒。

靜態(tài)屬性

以上介紹的關(guān)于類的所有屬性和方法,只有類在實(shí)例化時(shí)才會(huì)被初始化阅畴。實(shí)際上倡怎,我們也可以給類定義靜態(tài)屬性和方法。

因?yàn)檫@些屬性存在于類這個(gè)特殊的對(duì)象上,而不是類的實(shí)例上监署,所以我們可以直接通過(guò)類訪問(wèn)靜態(tài)屬性颤专,如下代碼所示:

class MyArray {

? static displayName = 'MyArray';

? static isArray(obj: unknown) {

? ? return Object.prototype.toString.call(obj).slice(8, -1) === 'Array';

? }

}

console.log(MyArray.displayName); // => "MyArray"

console.log(MyArray.isArray([])); // => true

console.log(MyArray.isArray({})); // => false

在第 2~3 行,通過(guò) static 修飾符钠乏,我們給 MyArray 類分別定義了一個(gè)靜態(tài)屬性 displayName 和靜態(tài)方法 isArray栖秕。之后,我們無(wú)須實(shí)例化 MyArray 就可以直接訪問(wèn)類上的靜態(tài)屬性和方法了晓避,比如第 8 行訪問(wèn)的是靜態(tài)屬性 displayName簇捍,第 9~10 行訪問(wèn)的是靜態(tài)方法 isArray。

基于靜態(tài)屬性的特性俏拱,我們往往會(huì)把與類相關(guān)的常量垦写、不依賴實(shí)例 this 上下文的屬性和方法定義為靜態(tài)屬性,從而避免數(shù)據(jù)冗余彰触,進(jìn)而提升運(yùn)行性能梯投。

靜態(tài)屬性特點(diǎn):

? ?1. 一聲明就被存儲(chǔ)在棧中,直接占據(jù)內(nèi)存况毅,可以快速穩(wěn)定的調(diào)用分蓖。

? ?2. 生命周期長(zhǎng),從jvm加載開始到j(luò)vm加載結(jié)束尔许。

? ?3. 全局唯一么鹤,在一個(gè)運(yùn)行環(huán)境中,靜態(tài)變量只有一個(gè)值味廊,任何一次修改都是全局性的影響蒸甜。

? ?4. 占據(jù)內(nèi)存,程序中應(yīng)該包含盡量少的static

注意:上邊我們提到了不依賴實(shí)例 this 上下文的方法就可以定義成靜態(tài)方法余佛,這就意味著需要顯式注解 this 類型才可以在靜態(tài)方法中使用 this柠新;非靜態(tài)方法則不需要顯式注解 this 類型,因?yàn)?this 的指向默認(rèn)是類的實(shí)例辉巡。

抽象類

接下來(lái)我們看看關(guān)于類的另外一個(gè)特性——抽象類恨憎,它是一種不能被實(shí)例化僅能被子類繼承的特殊類

我們可以使用抽象類定義派生類需要實(shí)現(xiàn)的屬性和方法郊楣,同時(shí)也可以定義其他被繼承的默認(rèn)屬性和方法憔恳,如下代碼所示:

abstract class Adder {

? abstract x: number;

? abstract y: number;

? abstract add(): number;

? displayName = 'Adder';

? addTwice(): number {

? ? return (this.x + this.y) * 2;

? }

}

class NumAdder extends Adder {

? x: number;

? y: number;

? constructor(x: number, y: number) {

? ? super();

? ? this.x = x;

? ? this.y = y;

? }

? add(): number {

? ? return this.x + this.y;

? }

}

const numAdder = new NumAdder(1, 2);

console.log(numAdder.displayName); // => "Adder"

console.log(numAdder.add()); // => 3

console.log(numAdder.addTwice()); // => 6

在第 1~10 行,通過(guò) abstract 關(guān)鍵字净蚤,我們定義了一個(gè)抽象類 Adder钥组,并通過(guò)abstract關(guān)鍵字定義了抽象屬性x、y及方法add今瀑,而且任何繼承 Adder 的派生類都需要實(shí)現(xiàn)這些抽象屬性和方法程梦。

同時(shí)腔丧,我們還在抽象類 Adder 中定義了可以被派生類繼承的非抽象屬性displayName和方法addTwice。

然后作烟,我們?cè)诘?12~23 行定義了繼承抽象類的派生類 NumAdder愉粤, 并實(shí)現(xiàn)了抽象類里定義的 x、y 抽象屬性和 add 抽象方法拿撩。如果派生類中缺少對(duì) x衣厘、y、add 這三者中任意一個(gè)抽象成員的實(shí)現(xiàn)压恒,那么第 12 行就會(huì)提示一個(gè) ts(2515) 錯(cuò)誤影暴,關(guān)于這點(diǎn)你可以親自驗(yàn)證一下。

抽象類中的其他非抽象成員則可以直接通過(guò)實(shí)例獲取探赫,比如第 26~28 行中型宙,通過(guò)實(shí)例 numAdder,我們獲取了 displayName 屬性和 addTwice 方法伦吠。

因?yàn)槌橄箢惒荒鼙粚?shí)例化妆兑,并且派生類必須實(shí)現(xiàn)繼承自抽象類上的抽象屬性和方法定義,所以抽象類的作用其實(shí)就是對(duì)基礎(chǔ)邏輯的封裝和抽象毛仪。

實(shí)際上搁嗓,我們也可以定義一個(gè)描述對(duì)象結(jié)構(gòu)的接口類型抽象類的結(jié)構(gòu),并通過(guò) implements 關(guān)鍵字約束類的實(shí)現(xiàn)箱靴。

使用接口與使用抽象類相比腺逛,區(qū)別在于接口只能定義類成員的類型,如下代碼所示:

interface IAdder {

? x: number;

? y: number;

? add: () => number;

}

class NumAdder implements IAdder {

? x: number;

? y: number;

? constructor(x: number, y: number) {

? ? this.x = x;

? ? this.y = y;

? }

? add() {

? ? return this.x + this.y;

? }

? addTwice() {

? ? return (this.x + this.y) * 2;

? }

}

在第 1~5 行衡怀,我們定義了一個(gè)包含 x棍矛、y、add 屬性和方法的接口類型抛杨,然后在第 6~12 行實(shí)現(xiàn)了擁有接口約定的x够委、y 屬性和 add 方法,以及接口未約定的 addTwice 方法的NumAdder類 蝶桶。

類的類型

類的最后一個(gè)特性——類的類型和函數(shù)類似慨绳,即在聲明類的時(shí)候,其實(shí)也同時(shí)聲明了一個(gè)特殊的類型(確切地講是一個(gè)接口類型)真竖,這個(gè)類型的名字就是類名,表示類實(shí)例的類型厌小;在定義類的時(shí)候恢共,我們聲明的除構(gòu)造函數(shù)外所有屬性、方法的類型就是這個(gè)特殊類型的成員璧亚。如下代碼所示:

class A {

? name: string;

? constructor(name: string) {

? ? this.name = name;

? }

}

const a1: A = {}; // ts(2741) Property 'name' is missing in type '{}' but required in type 'A'.

const a2: A = { name: 'a2' }; // ok

在第 1~6 行讨韭,我們?cè)诙x類 A ,也說(shuō)明我們同時(shí)定義了一個(gè)包含字符串屬性 name 的同名接口類型 A。因此透硝,在第 7 行把一個(gè)空對(duì)象賦值給類型是 A 的變量 a1 時(shí)狰闪,TypeScript 會(huì)提示一個(gè) ts(2741) 錯(cuò)誤,因?yàn)槿鄙?name 屬性濒生。在第 8 行把對(duì)象{ name: 'a2' }賦值給類型同樣是 A 的變量 a2 時(shí)埋泵,TypeScript 就直接通過(guò)了類型檢查,因?yàn)橛?name 屬性罪治。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末丽声,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子觉义,更是在濱河造成了極大的恐慌雁社,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晒骇,死亡現(xiàn)場(chǎng)離奇詭異霉撵,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)洪囤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門喊巍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人箍鼓,你說(shuō)我怎么就攤上這事崭参。” “怎么了款咖?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵何暮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我铐殃,道長(zhǎng)海洼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任富腊,我火速辦了婚禮坏逢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赘被。我一直安慰自己是整,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布民假。 她就那樣靜靜地躺著浮入,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羊异。 梳的紋絲不亂的頭發(fā)上事秀,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天彤断,我揣著相機(jī)與錄音,去河邊找鬼易迹。 笑死宰衙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的睹欲。 我是一名探鬼主播供炼,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼句伶!你這毒婦竟也來(lái)了劲蜻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤考余,失蹤者是張志新(化名)和其女友劉穎先嬉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楚堤,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疫蔓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了身冬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衅胀。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酥筝,靈堂內(nèi)的尸體忽然破棺而出滚躯,到底是詐尸還是另有隱情,我是刑警寧澤嘿歌,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布掸掏,位于F島的核電站,受9級(jí)特大地震影響宙帝,放射性物質(zhì)發(fā)生泄漏丧凤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一步脓、第九天 我趴在偏房一處隱蔽的房頂上張望愿待。 院中可真熱鬧,春花似錦靴患、人聲如沸仍侥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)访圃。三九已至,卻和暖如春相嵌,著一層夾襖步出監(jiān)牢的瞬間腿时,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工饭宾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留批糟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓看铆,卻偏偏與公主長(zhǎng)得像徽鼎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弹惦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

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