讓我們徹底搞懂閉包和精通函數(shù)

還記得開始學(xué)習(xí)前端吕朵,閉包作用域神馬的都非常難以理解绰垂,遇到面試只能提前去背嗅榕,其實(shí)被一仔細(xì)問都很難說出所以然顺饮,相信很多新手都有和我曾經(jīng)一樣的問題,所以我們今天來學(xué)習(xí)一下閉包和函數(shù)誊册,一起來了解這一部分吧~

????我們其實(shí)每天都在寫閉包领突,每天編碼都無時(shí)無刻的享受著閉包帶來的便利,我們的動(dòng)畫處理案怯,事件回調(diào)君旦,包括在一些框架中閉包一直都存在,閉包和作用域規(guī)則息息相關(guān)嘲碱,所以我們會(huì)連帶了解一下作用域相關(guān)知識(shí)金砍。

因卓誒;此文已同步到因卓誒blog?點(diǎn)擊訪問原文麦锯,獲得更好體驗(yàn)


?理解閉包

??????閉包允許函數(shù)訪問函數(shù)外部的變量恕稠,只要變量存在于聲明函數(shù)的作用域中即可訪問。所聲明的函數(shù)不會(huì)因?yàn)樽饔糜虻南ФХ鲂溃侨魏螘r(shí)間都可以調(diào)用鹅巍。

var?value?=?"我是外部變量";function?testFun(){  console.log(value);}testFun(); // 執(zhí)行函數(shù)

這樣子的代碼我們每天都在寫,其實(shí)它就是一個(gè)閉包料祠,我們可以把代碼套入到剛剛的概念中; 首先函數(shù)聲明和變量都在全局作用域中(符合在同樣的作用域概念)也滿足任何時(shí)間去調(diào)用testFun函數(shù)骆捧,但是我們拿這種簡單的例子體現(xiàn)不出閉包的作用。

// 一個(gè)更為直觀的閉包例子var?value?=?"shenhao";var?later = null;function?outsideFun(){??var?innerValue?=?"函數(shù)作用域聲明的變量";??function?insideFun(){????//?由于作用域鏈????console.log(value); // shenhao????console.log(innervalue); // 函數(shù)作用域聲明的變量??}??//?把內(nèi)部函數(shù)傳遞給later??later = insideFun;}outsideFun();later();

按照道理來說髓绽,執(zhí)行l(wèi)ater時(shí)候訪問變量敛苇,value肯定是有值的,因?yàn)樗嬖谟谌汁h(huán)境中顺呕,那么innerValue真的因?yàn)橥獠孔饔糜虻南Ф莕ull么枫攀,答案是不可能的,由于閉包原因株茶,我們還能訪問innerValue的值来涨。所以我們能得出一個(gè)結(jié)論:?當(dāng)在外部函數(shù)內(nèi)部創(chuàng)建一個(gè)函數(shù)的時(shí)候,還額外的創(chuàng)建了一個(gè)閉包忌卤,這個(gè)閉包包含了創(chuàng)建它時(shí)此作用域全部的變量扫夜,當(dāng)這個(gè)作用域消失的時(shí)候,那么閉包中還在驰徊,因此我們就可以在作用域消失之后還能訪問變量啦笤闯。

??那我們可以用一個(gè)圖來描述一下這個(gè)關(guān)系(此圖借鑒了js忍者秘籍第5章閉包相關(guān)內(nèi)容的氣泡圖)


閉包就可以使用這個(gè)圖來解釋,那么我們必須要記住的一點(diǎn)就是棍厂,通過閉包來訪問變量的函數(shù)都有一個(gè)作用域鏈颗味,作用域鏈保存著閉包的信息。

?????使用閉包的時(shí)候牺弹,所有的信息都會(huì)存儲(chǔ)在內(nèi)存中浦马,那么這些信息什么時(shí)候被銷毀,取決于JS引擎認(rèn)為這些信息不再使用才會(huì)被回收或者當(dāng)頁面卸載時(shí)张漂。


用閉包實(shí)現(xiàn)私有變量

開發(fā)者如果不止會(huì)一種編程語言晶默,那么肯定就知道私有變量這個(gè)概念,但是在JS中是不存在的航攒,但是我們可以使用閉包來構(gòu)建一個(gè)“類私有變量”磺陡,但是并不是完美真正的私有變量,我們看一下demo

function?Test(){? var?count?=?0;??this.addCount?=?function(){????count?++;??}??this.getCount?=?function(){????return?count;??}}
const?private?=?new?Test();private.addCount();private.getCount(); // 1

??? Test方法中的count就是我們所說的私有屬性漠畜,只能通過內(nèi)置的add和get方法才能對(duì)其操作币他,那么我們也可以構(gòu)造多個(gè)函數(shù),那么當(dāng)然不同函數(shù)中的count都是具有獨(dú)立性的憔狞。我們通過上述代碼簡單實(shí)現(xiàn)了一個(gè)私有屬性的例子蝴悉,就是通過閉包,外部通過內(nèi)部的函數(shù)去獲取/修改變量而外部不能直接去更改變量瘾敢。



回調(diào)函數(shù)callBack

當(dāng)我們做WEB應(yīng)用時(shí)候拍冠,做一些動(dòng)畫的需求,常見地要求我們同時(shí)操作好幾個(gè)DOM簇抵,操作好幾個(gè)動(dòng)畫狀態(tài)庆杜,那我們在學(xué)習(xí)閉包之前,都是在全局作用域去定義變量正压,然后去調(diào)用多個(gè)函數(shù)欣福,對(duì)應(yīng)的函數(shù)再去改變對(duì)應(yīng)的變量,這樣非常不好焦履,會(huì)造成代碼過于繁重且控制多個(gè)變量會(huì)非常麻煩拓劝。那么我們可以用閉包解決這個(gè)問題,假設(shè)我們需要改變2個(gè)動(dòng)畫區(qū)域嘉裤,我們可以這么寫郑临。

function?animated(elementID){??var?elem?=?document.getElementById(elementID);??var tick = 0;??var?timer?=?setInterval(() => {??  ...??})}

如果我們把tick和timer等變量挪到全局作用域中,那么我們控制多個(gè)elment的動(dòng)畫屑宠,將會(huì)產(chǎn)生大量的變量厢洞,如果我們通過閉包,計(jì)時(shí)器中的回調(diào)都可以操作對(duì)應(yīng)自己的私有變量,那么我們就可以這樣得出結(jié)論:

閉包不是一個(gè)創(chuàng)建函數(shù)時(shí)候的快照躺翻,而是一個(gè)可以在函數(shù)執(zhí)行的時(shí)候能夠修改變量的狀態(tài)封裝丧叽,只要閉包存在,我們就可以修改變量的值


執(zhí)行上下文跟蹤代碼

我們都知道JS是單線程的執(zhí)行模型公你,我們都知道JS有2種代碼類型踊淳,一種是全局代碼,一種是函數(shù)代碼陕靠,那么執(zhí)行上下文也分為全局執(zhí)行上下文和函數(shù)執(zhí)行上下文迂尝,全局執(zhí)行上下文則js程序開始時(shí)就創(chuàng)建了,函數(shù)執(zhí)行上下文那么就是函數(shù)執(zhí)行開始創(chuàng)建剪芥,那么我們可以看一個(gè)例子來了解一下:

<script>// 全局執(zhí)行上下文開始var start = "開始";function?method(){??//?函數(shù)執(zhí)行文開始}method();</script>

當(dāng)一個(gè)函數(shù)開始執(zhí)行垄开,則創(chuàng)建一個(gè)新的執(zhí)行上下文,執(zhí)行完畢則會(huì)關(guān)閉上下文回到創(chuàng)建時(shí)的執(zhí)行上下文接著執(zhí)行代碼税肪,所以JS為了跟蹤這種調(diào)用順序就要使用執(zhí)行上下文棧溉躲,也是大家熟悉的 “調(diào)用棧”寸认;

(PS:有那味了)

就像一個(gè)托盤一樣签财,盤子越壘越高,每一個(gè)盤子都是函數(shù)執(zhí)行棧偏塞,執(zhí)行完以后最終都會(huì)回歸到全局執(zhí)行棧中

執(zhí)行上下文除了可以定位執(zhí)行的函數(shù)之外唱蒸,在靜態(tài)環(huán)境下也可以準(zhǔn)確地定位到具體的標(biāo)識(shí)符噢。


作用域(詞法環(huán)境)

詞法環(huán)境又稱之為作用域灸叼,是js引擎內(nèi)部實(shí)現(xiàn)的一套跟蹤標(biāo)識(shí)符和變量映射關(guān)系的機(jī)制神汹,很多文章都沒有把詞法環(huán)境的概念講清楚,那么表達(dá)“映射關(guān)系”是最貼切的古今。

作用域是和js代碼息息相關(guān)的屁魏,那么在ES6初版的時(shí)候沒有塊級(jí)作用域的解決方案,所以從C捉腥,Java開發(fā)轉(zhuǎn)過來的開發(fā)者們就會(huì)覺得JS應(yīng)該也有這樣的概念氓拼,但是其實(shí)從ES6的let const之后才解決了這個(gè)問題。我們都知道這種作用域場景最直觀的表達(dá)就是代碼嵌套抵碟,那么我們寫一個(gè)例子:

var?all?=?"全局的變量"function a(){?var aValue = "a函數(shù)里面的變量"?function b(){???var?bValue = "b函數(shù)里面的變量"???for(var?c?=?0;?c<=10;?c++){?????console.log(all?+?aValue?+?bvalue + c); ???}?}}

JS引擎是如何跟蹤這些代碼桃漾,分析它們的結(jié)構(gòu),這就是詞法環(huán)境的作用拟逮。

執(zhí)行上下文對(duì)應(yīng)的詞法環(huán)境撬统,詞法環(huán)境中包含了上下文中定義標(biāo)識(shí)符映射表,所以for循環(huán)具有a和b的標(biāo)識(shí)符映射表敦迄,無論何時(shí)創(chuàng)建了函數(shù)恋追,那么會(huì)有一個(gè)與之對(duì)應(yīng)的詞法環(huán)境凭迹,那么這個(gè)詞法環(huán)境會(huì)存儲(chǔ)在[[Enviroment]]這個(gè)內(nèi)部屬性上,所以這就是JS引擎分析代碼之間關(guān)聯(lián)的重要原因苦囱。

那么現(xiàn)在我們已經(jīng)了解了基本的標(biāo)識(shí)符查找規(guī)則嗅绸,那么變量類型也是我們需要簡單了解的,盡管這比較簡單沿彭。


理解JS的變量類型

像我們現(xiàn)在討論的這個(gè)話題朽砰,基本是中小公司面試必問的尖滚,爛大街的let

?conat var 有什么區(qū)別喉刘?這個(gè)問題出鏡率實(shí)在太多了,網(wǎng)上給的答案也太多了漆弄,我們就根據(jù)剛剛所提到的知識(shí)點(diǎn)來總結(jié)一下:

可變性

詞法環(huán)境

const是無法改變的

let,const 比較var的區(qū)別則就是詞法環(huán)境不一樣睦裳,let和const解決了JS塊級(jí)作用域的缺陷。

社區(qū)中很多大佬或者某些公司的代碼規(guī)范中撼唾,出現(xiàn)了強(qiáng)制要求使用const替換var和let的事情廉邑,因?yàn)榉浅6啻a是因?yàn)樽兞康目勺冃栽斐傻腂UG,那么我們在日常開發(fā)中倒谷,其實(shí)是很少遇到只能通過變量的可變來做的需求蛛蒙,所以我認(rèn)為這種觀念還是蠻正確的,值得提倡

那么我們來深入const的工作原理渤愁,深層次的了解一下:

我們一般使用const是這樣的牵祟,第一是不會(huì)再次賦值的特殊變量或者是一個(gè)固定的值,比如我們在運(yùn)算的時(shí)候抖格,需要定義人數(shù)诺苹,數(shù)量諸如此類,也是為了JS代碼的運(yùn)行穩(wěn)定為程序優(yōu)化提供便利雹拄。

const a = "一次賦值";a = 1; // 重新賦一個(gè)新值  報(bào)錯(cuò)const?b = {};b.age = 20; // 不會(huì)報(bào)錯(cuò)const c = [];c.pus("1");?//?不會(huì)報(bào)錯(cuò)

const只允許初始化賦一次值收奔,以后如何有“新值”賦給const變量,則會(huì)報(bào)錯(cuò)滓玖,但是在const變量上對(duì)對(duì)象坪哄,數(shù)組的修改是允許的。

變量的可變性已經(jīng)描述完了势篡,現(xiàn)在我們可以看看變量的詞法環(huán)境的區(qū)別翩肌。

當(dāng)我們使用關(guān)鍵字var的時(shí)候,該變量的詞法環(huán)境是最近的函數(shù)內(nèi)部或者全局定義的殊霞,那么我們就可以用一個(gè)demo表示:

function?fun(){??for(var?i?=?0;i<10;i++){????var?thisMessage?=?"和變量i一個(gè)作用域"??}}

1.?從這個(gè)例子就可以看出摧阅,變量i是var定義的,所以它屬于最近的函數(shù)詞法環(huán)境內(nèi)绷蹲,所以變量i和thisMessage是同一個(gè)作用域棒卷,for循環(huán)中的變量i也因此忽略塊級(jí)作用域

所以很多文章教程中顾孽,包括我們?nèi)粘i_發(fā)的時(shí)候,在寫for循環(huán)中類似的臨時(shí)變量的時(shí)候比规,需要使用let定義變量若厚,避免在多個(gè)循環(huán)中(都在一個(gè)函數(shù)詞法環(huán)境中)會(huì)造成沖突。

那么我們使用let改寫此demo之后:

for(let?i?=?0;?i<10;i++)

那么我們可以在一個(gè)詞法環(huán)境中寫多個(gè)類似的代碼蜒什,從而不造成沖突测秸,外部詞法環(huán)境也無法訪問到i變量。

我們已經(jīng)了解了標(biāo)識(shí)符的定義和詞法環(huán)境相關(guān)知識(shí)灾常,那么我們下來應(yīng)該進(jìn)行深入探索在詞法環(huán)境中如何注冊標(biāo)識(shí)符霎冯。


注冊標(biāo)識(shí)符

我們?nèi)绻菑腏ava或者C轉(zhuǎn)JS的童鞋們,當(dāng)我們第一次接觸到下面的代碼钞瀑,你或許感覺到懵逼沈撞。

var?test?=?"我是一個(gè)測試變量";testFun(test);function?testFun(str){??return "Hello" + str;}

為什么我的函數(shù)還沒定義,就可以執(zhí)行雕什?我們都知道JS是逐行執(zhí)行代碼的缠俺,按道理說函數(shù)還沒執(zhí)行到聲明這一塊,是不可以調(diào)用testFun贷岸。那么JS是如何注冊函數(shù)的壹士,如何知道testFun的存在的呢?

JS在創(chuàng)建新的詞法環(huán)境的時(shí)候偿警,會(huì)執(zhí)行2步躏救。

?js會(huì)訪問并注冊在當(dāng)前詞法環(huán)境注冊的變量和函數(shù)

執(zhí)行代碼:取決于變量類型和詞法環(huán)境類型

那我們要細(xì)細(xì)分析一下這個(gè)注冊過程。

? ? 1. 首先如果是創(chuàng)建了函數(shù)詞法環(huán)境户敬,那么JS先會(huì)定義行參和參數(shù)默認(rèn)值

????2. 如果是全局詞法環(huán)境落剪,那么將會(huì)把函數(shù)聲明的代碼查詢到(函數(shù)表達(dá)式或者是箭頭函數(shù)都不會(huì)被查到)查詢到之后將會(huì)把值賦給函數(shù)同名的標(biāo)識(shí)符中,如果標(biāo)識(shí)符已存在將會(huì)被改寫尿庐,如果是塊級(jí)作用域則跳過此步驟忠怖。

? ? 3. 變量聲明會(huì)在函數(shù)和全局作用域中,找到當(dāng)前函數(shù)和其他函數(shù)中使用var聲明的變量以及在其他函數(shù)或者代碼塊之外的let和const變量抄瑟,在塊級(jí)作用域中查找let和const變量凡泣,如果不存在將賦值為undefined,存在即保留皮假。

總結(jié):JS注冊標(biāo)識(shí)符將依據(jù)當(dāng)前詞法環(huán)境進(jìn)行注冊鞋拟。

所以我們就可以解釋我們剛剛寫的demo出現(xiàn)的疑惑了,是因?yàn)镴S在第一階段中加載了全局詞法環(huán)境惹资,將會(huì)把函數(shù)聲明語句賦給一個(gè)新的標(biāo)識(shí)符贺纲,因此我們在第二個(gè)階段代碼執(zhí)行時(shí)能順利地取到函數(shù)。

那么我們在開發(fā)中不僅僅會(huì)遇到上面這種情況褪测,我們可能還會(huì)遇到函數(shù)標(biāo)識(shí)符重載的問題:

console.log(typeof fun); // functionvar fun = 3;function?fun(){}console.log(typeof fun); // number

這就涉及到一個(gè)概念叫做變量提升猴誊,例如函數(shù)聲明將提升到全局作用域頂部潦刃,變量聲明將提升到函數(shù)作用域頂部

那么我們來分析一下上述的代碼:

首先在第一個(gè)階段,函數(shù)聲明語句將把函數(shù)賦給同名標(biāo)識(shí)符懈叹,所以在代碼執(zhí)行的時(shí)候fun標(biāo)識(shí)符是有值的而且類型就是函數(shù)

然后當(dāng)進(jìn)行變量處理的時(shí)候乖杠,發(fā)現(xiàn)fun標(biāo)識(shí)符已被注冊所以不會(huì)被賦值undefind,當(dāng)代碼執(zhí)行時(shí)fun已被再次賦值為3澄成,所以第二個(gè)console打印出的類型是number


閉包工作原理

我們之前了解過閉包可以讓我們訪問函數(shù)創(chuàng)建的作用域的全部變量胧洒,也舉了幾個(gè)例子,比如動(dòng)畫處理和回調(diào)墨状。

我們將利用詞法環(huán)境和執(zhí)行上下文重新分析我們之前的demo卫漫,這將會(huì)對(duì)我們理解閉包會(huì)更有幫助。

1. 計(jì)數(shù)器私有變量的例子

function Test(){  var count = 0;  this.addCount = function(){    count ++;  }  this.getCount = function(){    return count;  }}

分析:我們通過new關(guān)鍵字調(diào)用Test這個(gè)構(gòu)造函數(shù)歉胶,我們在外部訪問addCount函數(shù)實(shí)際上就是創(chuàng)建了這個(gè)閉包汛兜,在我們執(zhí)行Test.addCount這樣的函數(shù)之前我們的執(zhí)行上下文是全局執(zhí)行上下文,因?yàn)槲覀冋{(diào)用函數(shù)會(huì)創(chuàng)建新的執(zhí)行上下文那么也會(huì)創(chuàng)建新的詞法環(huán)境通今,那么addCount這個(gè)詞法環(huán)境包含著創(chuàng)建這個(gè)函數(shù)的詞法環(huán)境,當(dāng)在addCount中找不到count變量那么就會(huì)從外部環(huán)境去尋找(因?yàn)榇藭r(shí)對(duì)象是活躍的肛根,count變量就在此對(duì)象中)辫塌,就是這么簡單...

我們理解了執(zhí)行上下文和詞法環(huán)境的作用,詞法環(huán)境主要的作用就是跟蹤函數(shù)中定義的變量派哲,新的執(zhí)行環(huán)境將創(chuàng)建新的詞法環(huán)境臼氨。

請(qǐng)注意,JS沒有真正的私有變量芭届,上面的demo我們可以改變它:

var testImport = {};var?Test?=?new?Test();testImport.getCount?=?Test.getCountconsole.log(testImport.getCount); // 可以訪問

2. 動(dòng)畫處理的例子

function animated(elementID){  var elem = document.getElementById(elementID);  var tick = 0;  var timer = setInterval(() => {    ...  })}animated("box1");animated("box2");

分析:我們調(diào)用了animated的2個(gè)方法也就創(chuàng)建了2個(gè)詞法環(huán)境储矩,同樣的我們也創(chuàng)建了新的執(zhí)行上下文,每個(gè)詞法環(huán)境都有對(duì)應(yīng)的elem褂乍,tick等變量持隧,我們在這個(gè)代碼中設(shè)置了setInterval這個(gè)函數(shù),只要有一個(gè)函數(shù)在訪問變量逃片,那么這個(gè)閉包就會(huì)一直存在屡拨,除非計(jì)時(shí)器被清除,隨后回調(diào)函數(shù)被執(zhí)行褥实,然后這個(gè)閉包會(huì)訪問創(chuàng)建閉包時(shí)候的變量呀狼,極大的簡化了代碼。


小結(jié)

我們徹底理解了閉包的概念损离,也通過安全氣泡的方法來加深我們對(duì)于詞法環(huán)境的理解哥艇,保存創(chuàng)建函數(shù)時(shí)的詞法環(huán)境我們是存儲(chǔ)[[Environment]]屬性中的。所以我們當(dāng)作用域消失還能訪問到創(chuàng)建時(shí)候的變量

????2. JS引擎通過執(zhí)行上下文棧(調(diào)用棧)來跟蹤代碼的執(zhí)行僻澎,每次調(diào)用函數(shù)都會(huì)有新的執(zhí)行上下文貌踏,并且像我們演示服務(wù)生托盤一樣推到最頂端

????3.?JS通過詞法環(huán)境來跟蹤標(biāo)識(shí)符(也就是作用域)

????4. 我們可以定義全局瓮增,函數(shù),局部作用域級(jí)別的變量

??? 5. 使用let const var關(guān)鍵字聲明變量時(shí)哩俭,我們理解了它們的區(qū)別:可再次賦值和是否可以局部作用域绷跑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凡资,隨后出現(xiàn)的幾起案子砸捏,更是在濱河造成了極大的恐慌,老刑警劉巖隙赁,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垦藏,死亡現(xiàn)場離奇詭異,居然都是意外死亡伞访,警方通過查閱死者的電腦和手機(jī)掂骏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厚掷,“玉大人弟灼,你說我怎么就攤上這事∶昂冢” “怎么了田绑?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抡爹。 經(jīng)常有香客問我掩驱,道長,這世上最難降的妖魔是什么冬竟? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任欧穴,我火速辦了婚禮,結(jié)果婚禮上泵殴,老公的妹妹穿的比我還像新娘涮帘。我一直安慰自己,他們只是感情好袋狞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布焚辅。 她就那樣靜靜地躺著,像睡著了一般苟鸯。 火紅的嫁衣襯著肌膚如雪同蜻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天早处,我揣著相機(jī)與錄音湾蔓,去河邊找鬼。 笑死砌梆,一個(gè)胖子當(dāng)著我的面吹牛默责,可吹牛的內(nèi)容都是我干的贬循。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼桃序,長吁一口氣:“原來是場噩夢啊……” “哼杖虾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起媒熊,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤奇适,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后芦鳍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚷往,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年柠衅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了皮仁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡菲宴,死狀恐怖贷祈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情裙顽,我是刑警寧澤付燥,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站愈犹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏闻丑。R本人自食惡果不足惜漩怎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嗦嗡。 院中可真熱鬧勋锤,春花似錦、人聲如沸侥祭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矮冬。三九已至谈宛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胎署,已是汗流浹背吆录。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼牧,地道東北人恢筝。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓哀卫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撬槽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子此改,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355