提升代碼的可讀性系列(一)--基礎(chǔ)篇

作者:自成
原文地址:凹凸實(shí)驗(yàn)室(http://aotu.io/notes/2016/03/31/readable/

提升代碼的可讀性系列(一)--基礎(chǔ)篇

編程是一門藝術(shù)活闪金,好的代碼應(yīng)該就像住的房子一樣捣染,有整體的框架,有門买鸽,有窗戶描沟,相互獨(dú)立又完美組合。你覺(jué)得門不夠結(jié)實(shí)钾虐,就拆下來(lái)?yè)Q個(gè)實(shí)心的读跷;你覺(jué)得窗戶不夠明亮就換個(gè)全玻璃的,總之對(duì)房子的其他部位沒(méi)有任何影響禾唁。所以說(shuō)每一個(gè)程序員都應(yīng)該有一顆設(shè)計(jì)師的心效览。本文主要從編碼變量荡短、處理錯(cuò)誤丐枉、對(duì)象等基礎(chǔ)方面進(jìn)行簡(jiǎn)單的探討,希望能對(duì)大家的工作有所幫助掘托。

1 編碼風(fēng)格

老生常談瘦锹,我們先從最基礎(chǔ)的編碼說(shuō)起吧!好的編碼規(guī)范不僅僅能夠提升代碼的可讀性與可維護(hù)性闪盔,提高團(tuán)隊(duì)的工作效率弯院,也能夠避開(kāi)一些低級(jí)的錯(cuò)誤,減少bug的隱患泪掀,提升程序員的自我修養(yǎng)听绳。編碼雖小,但卻是萬(wàn)丈高樓的基礎(chǔ)异赫,對(duì)于編寫清晰連貫的代碼來(lái)說(shuō)椅挣,每一個(gè)字符都是非常重要的。以下部分編碼規(guī)范參考自凹凸實(shí)驗(yàn)室塔拳。

1.1 縮進(jìn)

通常使用四個(gè)空格進(jìn)行代碼縮進(jìn)鼠证,有些也用tab來(lái)縮進(jìn),這主要根據(jù)團(tuán)隊(duì)的風(fēng)格跟個(gè)人喜好靠抑。

1.2 空格

  • 左括號(hào)與類名之間一個(gè)空格
  • 冒號(hào)與屬性值之間一個(gè)空格
  • 操作符前后
  • 匿名函數(shù)表達(dá)式之后等

1.3 空行

這是一個(gè)容易被大家忽略的點(diǎn)量九,但它所帶來(lái)的效果是毋庸置疑的!通常一段代碼的語(yǔ)義和另一段代碼不相關(guān)颂碧,就應(yīng)該用空行隔開(kāi)荠列,避免一大段的代碼揉在一起,比如:

  • 在方法之間稚伍;
  • 方法中的局部變量和第一條語(yǔ)句之間弯予;
  • 注釋之前;
  • 方法內(nèi)的邏輯片段之間个曙。

1.4 命名約定

有一位大師曾說(shuō)過(guò)锈嫩,計(jì)算機(jī)科學(xué)只存在兩個(gè)難題:緩存命名受楼。由此可見(jiàn)命名不僅是一門科學(xué),也是一門技術(shù)呼寸。通常情況下艳汽,變量與函數(shù)一般使用駝峰大小寫命名法,其中為了區(qū)分變量與函數(shù)对雪,變量命名前綴應(yīng)當(dāng)是名詞河狐,函數(shù)前綴應(yīng)當(dāng)是動(dòng)詞,也就是說(shuō)我們應(yīng)當(dāng)讓命名承載一定的含義瑟捣,因此要避免使用沒(méi)有意義的命名馋艺。

1.4 注釋

通常我們?cè)诰帉懲暌欢未a的短時(shí)間內(nèi),會(huì)清楚這段代碼的工作原理迈套。但是當(dāng)過(guò)一段時(shí)間再次回到代碼中捐祠,可能會(huì)花很長(zhǎng)的時(shí)間才能讀懂。這種情況下桑李,編寫注釋就變得尤為重要了踱蛀。

2 變量

首先說(shuō)一說(shuō)全局變量存在哪些的問(wèn)題吧!命名沖突贵白、測(cè)試難度大率拒、深耦合等等。在創(chuàng)建變量的時(shí)候禁荒,我們應(yīng)該注意以下幾個(gè)方面:

2.1 避免隱性的創(chuàng)建全局變量

什么是隱性的全局變量呢猬膨?官方的回答是:任何變量,如果未經(jīng)聲明圈浇,就為全局對(duì)象所有寥掐。啥意思呢?其實(shí)就是沒(méi)有加var聲明的磷蜀,請(qǐng)看下面的例子:

function obj() {
    name = "aotu";
    return name;
}

另外一種容易創(chuàng)建隱形全局變量的情況就是var聲明的鏈?zhǔn)劫x值,如下代碼所示:

function person() {
    var a = b = 1;
}

以上這段代碼的執(zhí)行結(jié)果是:a是局部變量百炬,b是全局變量褐隆,主要原因是從右至左的操作符優(yōu)先級(jí),它實(shí)際執(zhí)行的結(jié)果等同于:

var a = ( b = 0 );

綜上所述剖踊,隱式全局變量并不是我們平時(shí)用var聲明的變量庶弃,而是全局對(duì)象的屬性,既然是屬性德澈,那么它可以通過(guò)delete操作符刪除歇攻,但變量不可以,且在ES5 strict以上會(huì)拋出錯(cuò)誤梆造。

2.2 在函數(shù)頂部聲明變量

在javascript中缴守,聲明變量有一個(gè)“提升”的概念,即無(wú)論在函數(shù)哪里聲明,效果都等同于在函數(shù)頂部進(jìn)行聲明屡穗。所以我們統(tǒng)一把變量在函數(shù)頂部聲明贴捡,既有利于可讀性與可維護(hù)行,也不易出錯(cuò)村砂。

2.3 使用單一var模式

var a = 1,
    b = 1,
    c = 1;

這樣聲明的變量不僅可讀性好烂斋,而且可以防止變量在定義前就被使用的邏輯錯(cuò)誤,且編碼更少础废。

2.4 單全局變量方式

雖然全局變量的容易污染命名空間汛骂,但有些功能的需要,難以避免使用评腺,關(guān)鍵是我們應(yīng)該做到避免全局變量超出我們的掌控香缺,最佳的方法是依賴盡可能少的全局變量。我們可以使用單全局變量的方式來(lái)開(kāi)啟我們的項(xiàng)目歇僧,這種方式在許多的javascript類庫(kù)中都有這樣使用图张。如jQuery,它定義了兩個(gè)全局變量$jQuery诈悍。

3 UI松耦合

什么是松耦合祸轮?當(dāng)修改一個(gè)組件的邏輯,而對(duì)另一個(gè)組件沒(méi)有影響侥钳,就說(shuō)這叫松耦合适袜。通常一個(gè)大型的web應(yīng)用,都是由多人共同開(kāi)發(fā)維護(hù)舷夺,這時(shí)候松耦合顯得至關(guān)重要苦酱,假如你修改了某一處的代碼而影響了團(tuán)隊(duì)其他人的功能,這是非常不友好的给猾。通常我們主要注意以下幾點(diǎn):

  • 將javascript從css中抽離疫萤,如:避免使用css表達(dá)式。
  • 將css從javascript中抽離敢伸,如:避免使用javascript直接修改css扯饶,最佳的方法是操作css的className;
  • 將javascript從HTML中抽離,如:避免將函數(shù)直接嵌入到html執(zhí)行池颈,我們應(yīng)該盡量做到將所有的js代碼都放入外置文件中尾序,確保html中不會(huì)有內(nèi)聯(lián)的js代碼。
  • 將html從javascript中抽離躯砰,如避免在js中拼接html結(jié)構(gòu)每币,我們可以用模板引擎,也可以使用Vue琢歇、React等兰怠。

4 錯(cuò)誤處理

4.1 為什么要拋出錯(cuò)誤梦鉴?

在javascript開(kāi)發(fā)中,總是會(huì)悄無(wú)聲息的出現(xiàn)一些超出我們預(yù)期的痕慢,攜帶的信息稀少的尚揣,隱晦含糊的bug,讓我們措手不及掖举,大大增加了我們調(diào)試錯(cuò)誤快骗、定位錯(cuò)誤的難度,影響開(kāi)發(fā)效率塔次。假設(shè)錯(cuò)誤中包含這樣的信息:“由于某某情況方篮,導(dǎo)致某某函數(shù)執(zhí)行錯(cuò)誤”,那么励负,是不是馬上就可以開(kāi)始調(diào)試藕溅,而不用花大量的時(shí)候去定位錯(cuò)誤?

4.2 何時(shí)拋出錯(cuò)誤?

主要是辨識(shí)代碼中哪些部分继榆,在特定的情況下最后可能導(dǎo)致錯(cuò)誤巾表。這里的錯(cuò)誤,通常都是我們?cè)谒伎嫉倪^(guò)程中的一些可預(yù)期的錯(cuò)誤略吨。

4.3 怎樣拋出錯(cuò)誤集币?

4.3.1 使用try-catch

將可能引發(fā)錯(cuò)誤的代碼放在try塊中,處理錯(cuò)誤的代碼放在catch中翠忠,如:

try {
    someMethod();
} catch (ex) {
    catchError(ex);
}

也可以增加一個(gè)finally塊鞠苟,這里需注意的是:finally塊中的代碼塊不管是否有錯(cuò)誤發(fā)生,最后都會(huì)被執(zhí)行秽之。

4.3.2 throw

當(dāng)我們能清晰的捕捉到錯(cuò)誤的時(shí)候当娱,最好的做法就是拋出這個(gè)錯(cuò)誤店雅,避免在不經(jīng)意的時(shí)候又遇到它疑苫,讓大家尷尬航唆。這里需注意的是割择,當(dāng)遇到throw操作符時(shí),代碼會(huì)立即停止執(zhí)行:

throw new Error("method(): descdescdesc");

也可以自定義一個(gè)錯(cuò)誤類型捂敌⌒费荩總之阴颖,就是盡可能用最短的字符描述清楚:

throw { 
    name: "myErrorType",
    message: "arguments must be a DOM element",
    errorMethod: errorMethod
}

5 創(chuàng)建對(duì)象

5.1 對(duì)象字面量

所謂的對(duì)象字面量其實(shí)就是我們通常所說(shuō)的鍵值對(duì)哈希表愤诱,這種方式不僅富有表現(xiàn)力,可讀性好捐友,且字符更短淫半,沒(méi)有作用域解析。它的語(yǔ)法規(guī)則如下:

  • 對(duì)象包裝在大括號(hào)中
  • 逗號(hào)分隔屬性和方法
  • 用冒號(hào)分隔屬性名稱和屬性的值
var obj = {
    name: "aotu",
    job: "farmer",
    getName: function () {
        return this.name;
    }
}

//調(diào)用方式
obj.getName();

實(shí)現(xiàn)私有屬性

以上例子的name匣砖、job屬性都是可直接訪問(wèn)的科吭。有些時(shí)候我們可能想實(shí)現(xiàn)一些私有的屬性昏滴,然后提供一個(gè)公有的接口來(lái)對(duì)外訪問(wèn)。雖然javascript并沒(méi)有特殊的語(yǔ)法來(lái)表示私有对人、公共屬性和方法谣殊,但是可以通過(guò)匿名閉包來(lái)實(shí)現(xiàn),內(nèi)部的任意變量都不會(huì)暴露牺弄,來(lái)看以下代碼:

var obj;
   
(function () {
    //這樣就能實(shí)現(xiàn)私有成員
    var name = "aotu",
        job = "farmer";
       
    obj = {
        getName: function () {
            return name;
        }
    }
}())

更優(yōu)雅的寫法:

var obj = (function () {
    var name = "aotu",
        job = "farmer";

    return {
        getName: function () {
            return name;
        }
    }
}());

這種寫法也是模塊模式的基礎(chǔ)框架姻几,后續(xù)會(huì)有詳細(xì)介紹。

熟悉了這種模式之后它還有很多種玩法势告,比如可以像jQuery這樣鏈?zhǔn)秸{(diào)用:“$(‘#id’).siblings(‘ul’).find(“l(fā)i”).addClass();

var obj = {
    num: 0,
    add: function (arg) {
        this.num += arg;
        return this;
    },
    red: function (arg) {
        this.num -= arg;
        return this;
    },
    setTotal: function () {
        console.log(this.num);
    }
};

//調(diào)用方式
obj.add(5).red(2).setTotal(); //3

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

我們先來(lái)看看構(gòu)造函數(shù)的基礎(chǔ)框架:

function Obj() {
    //公有屬性
    this.name = "aotu";
    this.job = "farmer";
       
    //公有方法
    this.getName = function () {
        console.log(this.name);
    } 
}

//調(diào)用方式
var obj = new Obj();
obj.getName();

在使用new方式實(shí)例化構(gòu)造函數(shù)蛇捌,通常會(huì)經(jīng)歷以下幾個(gè)步驟:

  • 創(chuàng)建一個(gè)對(duì)象并且this變量引用了該對(duì)象,且繼承了該對(duì)象的原型咱台。
  • 屬性和方法被加入到this引用的對(duì)象中络拌。
  • 隱式的返回新對(duì)象。

忘記使用NEW的情況

當(dāng)然回溺,我們有時(shí)候會(huì)忘記使用new操作符實(shí)例化的情況春贸,然而這并不會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤,但構(gòu)造函數(shù)的this指向了全局對(duì)象遗遵,可能會(huì)發(fā)生邏輯錯(cuò)誤或者意外萍恕,來(lái)看下面執(zhí)行的結(jié)果:

var obj = Obj();
obj.getName(); //Cannot read property 'getInfo' of undefined

為了避免這種意外發(fā)生,我們也可以在構(gòu)造函數(shù)中檢查this是否為構(gòu)造函數(shù)的一個(gè)實(shí)例瓮恭,強(qiáng)制使用new操作符雄坪,繼續(xù)看下面的例子:

function Obj() {
    if(!(this instanceof Obj)){
        return new Obj();
    }

    this.name = "aotu";
    this.age = 25;

    this.getName = function () {
        console.log(this.name);
    } 
}

再看執(zhí)行的結(jié)果:

var obj = Obj();
obj.getName(); //"aotu"

靜態(tài)成員

在javascript中,并沒(méi)有特殊的語(yǔ)法來(lái)表示靜態(tài)成員屯蹦,但我們可以為構(gòu)造函數(shù)添加屬性這種方式來(lái)實(shí)現(xiàn)這種語(yǔ)法维哈,請(qǐng)看下面的例子:

//構(gòu)造函數(shù)
function Obj() {}

//添加靜態(tài)方法
Obj.getAge = function () {
    console.log(25); 
}

//注意這里的調(diào)用方式
Obj.getAge(); //25

//如果使用實(shí)例對(duì)象調(diào)用
obj.getAge(); //Object #<Obj> has no method 'getAge'

這里大家需要注意調(diào)用靜態(tài)方法的方式,若以實(shí)例對(duì)象調(diào)用一個(gè)靜態(tài)方法是無(wú)法正常運(yùn)行的登澜,反之同理阔挠。

私有屬性與方法

在以上例子中,構(gòu)造函數(shù)的屬性與方法都屬于公有方法脑蠕,我們也可以給構(gòu)造函數(shù)添加私有方法與私有屬性:

function Obj() {
    this.name = "auto";
    this.age = 25;
     
    //私有屬性
    var address = "sz",
        that = this;
      
    //私有方法
    function getAddress() {
        console.log(that.address);
    }
       
    this.getName = function () {
        console.log(this.name);
    } 
}

構(gòu)造函數(shù)存在的問(wèn)題

構(gòu)造函數(shù)的主要問(wèn)題就是當(dāng)多次實(shí)例化這個(gè)構(gòu)造函數(shù)的時(shí)候购撼,每個(gè)方法都會(huì)重新創(chuàng)建一遍,這樣就等于在內(nèi)存中的拷貝谴仙。解決問(wèn)題的第一種思路迂求,就是將函數(shù)中的方法通過(guò)函數(shù)定義轉(zhuǎn)移到函數(shù)外面,并將指針傳遞給構(gòu)造函數(shù)晃跺,來(lái)看下面的例子:

function Obj() {
    this.name = "aotu";
    this.age = 25;

    //將指針賦給getName
    this.getName = getName;
}
  
function getName () {
    console.log(this.name);
}   

var obj1 = new Obj();
var obj2 = new Obj()

雖然也解決了以上的問(wèn)題揩局,但并沒(méi)有達(dá)到封裝的效果。接下來(lái)我們引入原型prototype的概念掀虎。

5.3 原型模式

每一個(gè)構(gòu)造函數(shù)都有一個(gè)原型prototype凌盯,原型對(duì)象包含一個(gè)指向構(gòu)造函數(shù)的指針付枫,這個(gè)指針指向一個(gè)可以由特定類型的所有實(shí)例共享的屬性和方法,所以使用原型對(duì)象可以讓所有對(duì)象實(shí)例共享它的屬性和方法驰怎,來(lái)看下面的例子:

function Obj() {}

Obj.prototype.name = "aotu";
Obj.prototype.age = 25;
Obj.prototype.getName = function () {
    console.log(this.name);
}

//調(diào)用方式

var obj1 = new Obj();
obj1.getName() //"aotu"

var obj2 = new Obj();
obj2.getName() //"aotu"

alert(obj1.getName == obj2.getName); //true

由此可見(jiàn)obj1obj2訪問(wèn)的是同一個(gè)getName函數(shù)阐滩。

更好的寫法

我們可以將所有的原型都寫在一個(gè)對(duì)象字面量里,這樣整個(gè)代碼看起來(lái)更加簡(jiǎn)潔清晰县忌,繼續(xù)往下看:

function Obj() {}

Obj.prototype = {
    name: "aotu",
    age: 25,
    getName: function () {
        return this.name;
    }
}

使用字面量的方式需注意的問(wèn)題

在使用這種字面量的方式的時(shí)候掂榔,需注意以下兩點(diǎn):

1.將prototype設(shè)置為等于一個(gè)對(duì)象字面量形式創(chuàng)建的對(duì)象,它本質(zhì)上已經(jīng)完全重寫了默認(rèn)的prototype對(duì)象芹枷,最終結(jié)果雖然相同衅疙,但是其constructor屬性不再指向該對(duì)象。

constructor是個(gè)什么鬼鸳慈?在默認(rèn)情況下饱溢,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor,它指向prototype屬性所在函數(shù)的指針走芋,換句話說(shuō)這個(gè)constructor就是指這個(gè)構(gòu)造函數(shù)绩郎。以上代碼執(zhí)行結(jié)果如下所示:

var obj= new Obj();
alert(obj.cnstructor == Obj) //false;

我們可以在重寫prototype的時(shí)候給constructor指定構(gòu)造函數(shù),接著往下看:

function Obj(){}

Obj.prototype = {
    constructor: Obj,
    name: "aotu",
    age: 25,
    getName: function () {
        return this.name;
    }
}

var obj= new Obj();
alert(obj.cnstructor == Obj) //true;

2.當(dāng)我們重寫整個(gè)原型的時(shí)候如果先創(chuàng)建了實(shí)例翁逞,就會(huì)切斷構(gòu)造函數(shù)與原型之間的聯(lián)系肋杖,因?yàn)?strong>實(shí)例的指針僅僅指向原型,而不是構(gòu)造函數(shù)挖函,在實(shí)際的操作過(guò)程中状植,應(yīng)該盡量避免這種錯(cuò)誤。

function Obj() { }

var obj = new Obj();

Obj.prototype = {
    constructor: Obj,
    name: "aotu",
    age: 25,
    getName: function () {
        return this.name;
    }
}

obj.getName();  //error

組合使用二者

在我們的具體應(yīng)用中怨喘,通常比較多的是組合使用構(gòu)造函數(shù)模式與原型模式津畸。構(gòu)造函數(shù)用于定義實(shí)例屬性,原型用于定于共享的屬性和方法必怜,這樣能夠最大限度的節(jié)省內(nèi)存肉拓。以下是一個(gè)基本的組合使用構(gòu)造函數(shù)與原型的例子:

function Obj(){
    if(!(this instanceof Obj)){
        return new Obj();
    }

    this.name = "aotu";
    this.age = 25;
}

Obj.prototype = {
    constructor: Obj,
    getName: function () {
        return this.name;
    }
}

var obj = Obj();
obj.getName();

5.4 模塊模式

模塊模式是一種非常通用的模式,也是使用頻率比較高的模式梳庆,它具有以下幾個(gè)特點(diǎn):

  • 模塊化
  • 可復(fù)用
  • 松耦合
  • 區(qū)分了私有方法與公共方法

我們先看看模塊模式的基礎(chǔ)框架:

var testModule = function () {
    //私有成員
    var testNode = document.getElementById("test");

    //也可在此定義私有方法
    function privateMethod() {
        console.log("this is Private method!");
    }

    return {
        //對(duì)外公開(kāi)的方法
        setHtml: function (txt) {
            testNode.innerHTML = txt;
        }
    }
}

//調(diào)用方式
var testModule = new testModule();
testModule.setHtml("Hello");

這種方式看起來(lái)比較清晰暖途、簡(jiǎn)潔。但就是每次調(diào)用的時(shí)候都需要用new來(lái)實(shí)例化膏执。我們知道每個(gè)實(shí)例在內(nèi)存里都是一份拷貝驻售,如何解決這個(gè)問(wèn)題呢?我們可以采用一個(gè)匿名閉包來(lái)完美的解決這個(gè)問(wèn)題更米。

(function () {
   //將所有的變量和function放在這里聲明芋浮,其作用域也只能在這個(gè)匿名閉包里面,既達(dá)到了封裝的目的,也能防止命名沖突
}())

接下來(lái)我們將它應(yīng)用到具體的實(shí)例中壳快,以下就是一個(gè)基本的Module模式:

var testModule =(function () {
    var my = {},
        testNode = document.getElementById("test");
     
    my.setHtml = function(txt) {
        testNode.innerHTML = txt;
    }
    
    return my;
} ())

//調(diào)用方式
testModule.setHtml("Hello");

通常在一個(gè)大型的項(xiàng)目中纸巷,會(huì)有多人共同開(kāi)發(fā)一個(gè)功能的情況,這個(gè)時(shí)候我們可以運(yùn)用這種模式將全局變量當(dāng)作參數(shù)傳遞眶痰,然后通過(guò)變量返回瘤旨,從而達(dá)到多人協(xié)作的目的。

var testModule =(function (my) {
    var testNode = document.getElementById("test");
     
    my.setHtml = function(txt) {
        testNode.innerHTML = txt;
    }
    
    return my;
} (testModule || {}))

我們也可以通過(guò)這個(gè)模式將私有的對(duì)象或者屬性保護(hù)起來(lái)竖伯,然后設(shè)置一些公共接口對(duì)外訪問(wèn)存哲,繼續(xù)來(lái)看下面的代碼:

var testModule =(function () {
    var testNode = document.getElementById("test"),
     
        setHtml = function(txt) {
            testNode.innerHTML = txt;
        };

        //設(shè)置公共調(diào)用方法
        return {
            setHtml: setHtml
        }
    } ())

以上幾種方式僅僅只是一些創(chuàng)建對(duì)象的基礎(chǔ),通過(guò)靈活運(yùn)用這些基礎(chǔ)七婴,可以變換出傳說(shuō)中各種各樣的模式祟偷,如迭代器模式、工廠模式打厘、裝飾者模式等修肠。對(duì)于后續(xù)學(xué)習(xí)其他的技術(shù)也是極有幫助的。如React:

var MyTitle = React.createClass({
    getDefaultProps : function () {
        return {
            title : 'Hello World'
        };
    },

    render: function() {
        return <h1> {this.props.title} </h1>;
    }
});

Vue:

new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue.js!'
    },
    methods: {
        reverseMessage: function () {
            this.message = this.message.split('').reverse().join('')
        }
    }
})

以上就是本期的所有內(nèi)容户盯,如有錯(cuò)漏嵌施,懇請(qǐng)指正,大家共同進(jìn)步莽鸭!在下一期中吗伤,會(huì)繼續(xù)跟大家探討更多好玩的東西,敬請(qǐng)期待硫眨。

6 參考資料

  • 《編寫可維護(hù)的JavaScript》[美] Nicholas C. Zakas 著
  • 《JavaScript設(shè)計(jì)模式》[美] Addy Osmani 著
  • 《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》
  • 博文:深入理解JavaScript系列
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末足淆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子礁阁,更是在濱河造成了極大的恐慌巧号,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氮兵,死亡現(xiàn)場(chǎng)離奇詭異裂逐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泣栈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門卜高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人南片,你說(shuō)我怎么就攤上這事掺涛。” “怎么了疼进?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)伞广。 經(jīng)常有香客問(wèn)我拣帽,道長(zhǎng)疼电,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任减拭,我火速辦了婚禮蔽豺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拧粪。我一直安慰自己修陡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布可霎。 她就那樣靜靜地躺著魄鸦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪癣朗。 梳的紋絲不亂的頭發(fā)上拾因,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音斯棒,去河邊找鬼盾致。 笑死,一個(gè)胖子當(dāng)著我的面吹牛荣暮,可吹牛的內(nèi)容都是我干的庭惜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼穗酥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼护赊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起砾跃,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤骏啰,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后抽高,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體判耕,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年翘骂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壁熄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碳竟,死狀恐怖草丧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情莹桅,我是刑警寧澤昌执,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響懂拾,放射性物質(zhì)發(fā)生泄漏煤禽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一委粉、第九天 我趴在偏房一處隱蔽的房頂上張望呜师。 院中可真熱鬧,春花似錦贾节、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至祈争,卻和暖如春斤程,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背菩混。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工忿墅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沮峡。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓疚脐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親邢疙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棍弄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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