JavaScript 論代碼執(zhí)行上下文

導(dǎo)讀

本片文章售淡,在前人的基礎(chǔ)上,加上自己的理解,解釋一下JavaScript的代碼執(zhí)行過(guò)程揖闸,順道介紹一下執(zhí)行環(huán)境和閉包的相關(guān)概念揍堕。

分為兩部分。第一部分是了解執(zhí)行環(huán)境的相關(guān)概念汤纸,第二部分是通過(guò)實(shí)際代碼了解具體執(zhí)行過(guò)程中執(zhí)行環(huán)境的切換衩茸。

執(zhí)行環(huán)境

執(zhí)行環(huán)境的分類

  • 1.全局執(zhí)行環(huán)境
    是JS代碼開(kāi)始運(yùn)行時(shí)的默認(rèn)環(huán)境(瀏覽器中為window對(duì)象)。全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象贮泞。
  • 2.函數(shù)執(zhí)行環(huán)境
    當(dāng)某個(gè)函數(shù)被調(diào)用時(shí)楞慈,會(huì)先創(chuàng)建一個(gè)執(zhí)行環(huán)境及相應(yīng)的作用域鏈。然后使用arguments和其他命名參數(shù)的值來(lái)初始化執(zhí)行環(huán)境的變量對(duì)象啃擦。
  • 3.使用eval()執(zhí)行代碼

沒(méi)有塊級(jí)作用域(本文不涉及ES6中let等概念)

執(zhí)行上下文(執(zhí)行環(huán)境)的組成

執(zhí)行環(huán)境(execution context囊蓝,EC)或稱之為執(zhí)行上下文,是JS中一個(gè)極為重要的概念议惰。當(dāng)JavaScript代碼執(zhí)行時(shí)慎颗,會(huì)進(jìn)入不同的執(zhí)行上下文,而每個(gè)執(zhí)行上下文的組成言询,基本如下:

  • 變量對(duì)象(Variable object俯萎,VO): 變量對(duì)象,即包含變量的對(duì)象运杭,除了我們無(wú)法訪問(wèn)它外夫啊,和普通對(duì)象沒(méi)什么區(qū)別
  • [[Scope]]屬性:數(shù)組。作用域鏈?zhǔn)且粋€(gè)由變量對(duì)象組成的帶頭結(jié)點(diǎn)的單向鏈表辆憔,其主要作用就是用來(lái)進(jìn)行變量查找撇眯。而[[Scope]]屬性是一個(gè)指向這個(gè)鏈表頭節(jié)點(diǎn)的指針。
  • this: 指向一個(gè)環(huán)境對(duì)象虱咧,注意是一個(gè)對(duì)象熊榛,而且是一個(gè)普通對(duì)象,而不是一個(gè)執(zhí)行環(huán)境玄坦。

若干執(zhí)行上下文會(huì)構(gòu)成一個(gè)執(zhí)行上下文棧(Execution context stack,ECS)绘沉。而所謂的執(zhí)行上下文棧,舉個(gè)例子择懂,比如下面的代碼

var a = "global var";

function foo(){
    console.log(a);
}

function outerFunc(){
    var b = "var in outerFunc";
    console.log(b);
    
    function innerFunc(){
        var c = "var in innerFunc";
        console.log(c);
        foo();
    }
    
    innerFunc();
}


outerFunc()

代碼首先進(jìn)入Global Execution Context赂弓,然后依次進(jìn)入outerFunc绑榴,innerFunc和foo的執(zhí)行上下文,執(zhí)行上下文棧就可以表示為:

執(zhí)行全局代碼時(shí)窃诉,會(huì)產(chǎn)生一個(gè)執(zhí)行上下文環(huán)境杨耙,每次調(diào)用函數(shù)都又會(huì)產(chǎn)生執(zhí)行上下文環(huán)境。當(dāng)函數(shù)調(diào)用完成時(shí)飘痛,這個(gè)上下文環(huán)境以及其中的數(shù)據(jù)都會(huì)被消除珊膜,再重新回到全局上下文環(huán)境。處于活動(dòng)狀態(tài)的執(zhí)行上下文環(huán)境只有一個(gè)。

產(chǎn)生執(zhí)行上下文的兩個(gè)階段

當(dāng)一段JS代碼執(zhí)行的時(shí)候,JS解釋器會(huì)通過(guò)兩個(gè)階段去產(chǎn)生一個(gè)EC

  • 創(chuàng)建階段(當(dāng)函數(shù)被調(diào)用描沟,但是開(kāi)始執(zhí)行函數(shù)內(nèi)部代碼之前)
    • 創(chuàng)建變量對(duì)象VO
    • 設(shè)置[[Scope]]屬性的值
    • 設(shè)置this的值
    • 激活/代碼執(zhí)行階段
  • 初始化變量對(duì)象饭寺,即設(shè)置變量的值、函數(shù)的引用厚脉,然后解釋/執(zhí)行代碼。

創(chuàng)建變量對(duì)象VO過(guò)程

  • 1.根據(jù)函數(shù)的參數(shù),創(chuàng)建并初始化arguments object
  • 2.掃描函數(shù)內(nèi)部代碼塑陵,查找函數(shù)聲明(function declaration)
    • 對(duì)于所有找到的函數(shù)聲明,將函數(shù)名和函數(shù)引用存入VO中
    • 如果VO中已經(jīng)有同名函數(shù)蜡励,那么就進(jìn)行覆蓋
  • 3.掃描函數(shù)內(nèi)部代碼令花,查找變量聲明(Variable declaration)
    • 對(duì)于所有找到的變量聲明(通過(guò)var聲明),將變量名存入VO中凉倚,并初始化為undefined
    • 如果變量名跟已經(jīng)聲明的形參或函數(shù)相同兼都,則什么也不做

注:步驟2和3也稱為聲明提升(declaration hoisting)

通過(guò)一段代碼來(lái)了解JavaScript代碼的執(zhí)行

我們舉例說(shuō)明,假如我們有一個(gè)js文件稽寒,內(nèi)容如下:

var  global_var1 = 10;
function  global_function1(parameter_a){
    var  local_var1 = 10 ;
    return  local_var1 + parameter_a + global_var1;
}
var global_sum = global_function1(10);
alert(global_sum);

下面我們來(lái)一步一步說(shuō)明解釋器是如何執(zhí)行這段代碼的:

1.創(chuàng)建全局上下文

首先扮碧,在解釋器眼中,global_var1瓦胎、global_sum叫做全局變量芬萍,因?yàn)樗鼈儾粚儆谌魏魏瘮?shù)。local_var1叫做局部變量搔啊,因?yàn)樗x在函數(shù)global_function1內(nèi)部柬祠。global_function1叫做全局函數(shù),因?yàn)樗鼪](méi)有定義在任何函數(shù)內(nèi)部负芋。

然后漫蛔,解釋器開(kāi)始掃描這段代碼嗜愈,為執(zhí)行這段代碼做了一些準(zhǔn)備工作——創(chuàng)建了一個(gè)全局上下文

全局上下文莽龟,可以把它看成一個(gè)JavaScript對(duì)象蠕嫁,姑且稱之為global_context。這個(gè)對(duì)象是解釋器創(chuàng)建的毯盈,當(dāng)然也是由解釋器使用剃毒。(我們的JavaScript代碼是接觸不到這個(gè)對(duì)象的)

global_context對(duì)象大概是這個(gè)樣子的:

global_context = {
       Variable_Object :{......},
       Scope           :[......],
       this            :{......}
}

可以看到,global_context有三個(gè)屬性

  • Variable_Object(以下簡(jiǎn)稱VO)
    {
    global_var1:undefined
    global_function1:函數(shù) global_function1的地址
    global_sum:undefined
    }

    解釋器在VO中記錄了變量全局變量global_var1搂赋、global_sum赘阀,但它們的值現(xiàn)在是undefined的,還記錄了全局函數(shù)global_function1脑奠,但是沒(méi)有記錄局部變量local_var1基公。VO的原型是Object.prototype

  • Scope數(shù)組中的內(nèi)容如下:

      [     global_context.Variable_Object     ]
    

    我們看到宋欺,Scope數(shù)組中只有一個(gè)對(duì)象轰豆,就是前面剛創(chuàng)建的對(duì)象VO。

  • this

    this的值現(xiàn)在是undefined

global_context對(duì)象被解釋器壓入一個(gè)棧中齿诞,不妨叫這個(gè)棧為context_stack∷嵝荩現(xiàn)在的context_stack是這樣的:

創(chuàng)建出global_context后,解釋器又偷偷摸摸干了一件事掌挚,它給global_function1設(shè)置了一個(gè)內(nèi)部屬性雨席,也叫scope,它的值就是global_context中的scope吠式!也就是說(shuō)陡厘,現(xiàn)在:

global_function1.scope === [  global_context.Variable_Object   ];

我們獲取不到global_function1的scope屬性的,只有解釋器自己能獲取到特占。

2.逐行執(zhí)行代碼

解釋器在創(chuàng)建了全局上下文后糙置,就開(kāi)始執(zhí)行這段代碼了。

第一句:

var  global_var1 = 10;

解釋器會(huì)把VO中的global_var1屬性的值設(shè)為10∈悄浚現(xiàn)在global_context對(duì)象變成了這樣:

global_context = {
       Variable_Object :{ 
               global_var1:10,
               global_function1:函數(shù) global_function1的地址,
               global_sum:undefined
        },
        Scope          :[ global_context.Variable_Object ],
        this           :undefined
}

第二句:

解釋器繼續(xù)執(zhí)行我們的代碼谤饭,它碰到了聲明式函數(shù)global_function1,由于在創(chuàng)建global_context對(duì)象時(shí)懊纳,它就已經(jīng)記錄好了該函數(shù)揉抵,所以現(xiàn)在它什么也不用做。

第三句:

var global_sum = global_function1(10);

解釋器看到嗤疯,我們?cè)谶@里調(diào)用了函數(shù)global_function1(解釋器已經(jīng)提前在global_context的VO中記錄下了global_function1冤今,所以它知道我們這里是一個(gè)函數(shù)調(diào)用),并且傳入了一個(gè)參數(shù)10茂缚,函數(shù)的返回結(jié)果賦值給了全局變量global_sum戏罢。

解釋器并沒(méi)有立即執(zhí)行函數(shù)中的代碼屋谭,因?yàn)樗獮楹瘮?shù)global_function1創(chuàng)建一個(gè)專門(mén)的context,我們叫它執(zhí)行上下文(execute_context)吧龟糕,因?yàn)槊慨?dāng)解釋器要執(zhí)行一個(gè)函數(shù)時(shí)桐磁,都會(huì)創(chuàng)建一個(gè)類似的context。

execute_context也是一個(gè)對(duì)象讲岁,并且與global_context還很像我擂,下面是它里面的內(nèi)容:

execute_context = {
       Variable_Object :{ 
               parameter_a:10,
               local_var1:undefined,
               arguments:[10]              
        },
        Scope          :[execute_context.Variable_Object, global_context.Variable_Object ],
        this           :undefined
}

我們看到,execute_context與global_context相比催首,有以下幾點(diǎn)變化:

  • VO
    • 首先記錄了函數(shù)的形式參數(shù)parameter_a扶踊,并且給它賦值10,這個(gè)10就是我們調(diào)用函數(shù)時(shí)傳遞進(jìn)去的郎任。
    • 然后記錄了函數(shù)體內(nèi)的局部變量local_var1,它的值還是undefined备籽。
    • 然后是一個(gè)arguments屬性舶治,它的值是一個(gè)數(shù)組,里面只有一個(gè)10车猬。

你可能疑惑霉猛,不是已經(jīng)在parameter_a中記錄了參數(shù)10了嗎,為什么解釋器還要搞一個(gè)arguments珠闰,再來(lái)記錄一遍呢惜浅?原因是如果我們這樣調(diào)用函數(shù):

global_function1(10,20,30);

在JavaScript中是不違法的。此時(shí)VO中的arguments會(huì)變成這樣:

arguments:[10,20,30]

parameter_a的值還是10伏嗜√诚ぃ可見(jiàn),arguments是專門(mén)記錄我們傳進(jìn)去的所有參數(shù)的承绸。

  • Scope

Scope屬性仍然是一個(gè)數(shù)組裸影,只不過(guò)里面的元素多了個(gè)execute_context.Variable_Object,并且排在了global_context.Variable_Object前面军熏。

解釋器是根據(jù)什么規(guī)則決定Scope中的內(nèi)容的呢轩猩?答案非常簡(jiǎn)單:

execute_context.Scope = execute_context.Variable_Object + global_function1.scope。

也就是說(shuō)荡澎,每當(dāng)要執(zhí)行一個(gè)函數(shù)時(shí)均践,解釋器都會(huì)將執(zhí)行上下文(execute_context)中Scope數(shù)組的第一個(gè)元素設(shè)為該執(zhí)行上下文(execute_context)的VO對(duì)象,然后取出函數(shù)創(chuàng)建時(shí)保存在函數(shù)中的scope屬性(本文中則是global_function1.scope)摩幔,將其添加到執(zhí)行上下文(execute_context)Scope數(shù)組的后面彤委。

我們知道,global_function1是在global_context下創(chuàng)建的热鞍,創(chuàng)建的時(shí)候葫慎,它的scope屬性被設(shè)置成了global_context的Scope衔彻,里面只有一個(gè)global_context.Variable_Object,于是這個(gè)對(duì)象被添加到execute_context.Scope數(shù)組中execute_context.Variable_Object對(duì)象后面偷办。

任何一個(gè)函數(shù)在創(chuàng)建時(shí)艰额,解釋器都會(huì)把它所在的執(zhí)行上下文或者全局上下文的Scope屬性對(duì)應(yīng)的數(shù)組設(shè)置給函數(shù)的scope屬性,這個(gè)屬性是函數(shù)“與生俱來(lái)”的椒涯。

  • this
    this的值此時(shí)仍然是undefined的(但不同的解釋器可能有不同的賦值)

解釋器為函數(shù)global_function1創(chuàng)建好了execute_context(執(zhí)行上下文)后柄沮,會(huì)把這個(gè)上下文對(duì)象壓入context_stack中,所以废岂,現(xiàn)在的context_stack是這樣的:

準(zhǔn)備執(zhí)行函數(shù)內(nèi)的代碼

做好了準(zhǔn)備工作祖搓,解釋器開(kāi)始執(zhí)行函數(shù)里面的代碼了,此時(shí)我們稱函數(shù)是在執(zhí)行上下文中運(yùn)行的湖苞。

第一句

var  local_var1 = 10 ;

它的處理辦法很簡(jiǎn)單拯欧,將execute_context的VO中的local_var1賦值為10。這一點(diǎn)與在global_context下執(zhí)行的變量賦值語(yǔ)句的處理一樣财骨。此時(shí)的execute_context變成這樣:

execute_context = {
       Variable_Object :{ 
               parameter_a:10,
               local_var1:10,                      //為local_var1賦值10
               arguments:[10]              
        },
        Scope          :[execute_context.Variable_Object, global_context.Variable_Object ],
        this           :undefined
}

第二句

return local_var1 + parameter_a + global_var1;
  • 解釋器進(jìn)一步考察語(yǔ)句镐作,發(fā)現(xiàn)這是一個(gè)返回語(yǔ)句,于是它開(kāi)始計(jì)算return 后面的表達(dá)式的值隆箩。
  • 在表達(dá)式中它首先碰到了變量local_var1该贾,它首先在execute_context的Scope中依次查找,在第一個(gè)元素execute_context的VO發(fā)現(xiàn)了local_var1捌臊,并且知道它的值是10
  • 然后解釋器繼續(xù)前進(jìn)杨蛋,碰到了變量parameter_a,它如法炮制理澎,在execute_context的VO中發(fā)現(xiàn)了parameter_a逞力,并且確定它的值是10。
  • 接著發(fā)現(xiàn) global_var1矾端,解釋器從execute_context的Scope第一個(gè)元素execute_context.VO中查找掏击,沒(méi)有發(fā)現(xiàn)global_var1。繼續(xù)查看Scope數(shù)組的第二個(gè)元素秩铆,即global_context.VO砚亭,發(fā)現(xiàn)并且確定了它的值為10。
  • 于是殴玛,解釋器將三個(gè)變量值相加得到了30捅膘,然后就返回了。
  • 此時(shí)滚粟,解釋器知道函數(shù)已經(jīng)執(zhí)行完了寻仗,那么它為這個(gè)函數(shù)創(chuàng)建的執(zhí)行上下文也沒(méi)有用了,于是凡壤,它將execute_context從context_stack中彈出署尤,由于沒(méi)有其他對(duì)象引用著execute_context耙替,解釋器就把它銷毀了。現(xiàn)在context_stack中又只剩下了global_context曹体。

第三句

var global_sum = 30;

現(xiàn)在解釋器又回到全局上下文中執(zhí)行代碼了俗扇,這時(shí)它要把30賦值給sum,方法就是更改global_context中的VO對(duì)象的global_sum屬性的值箕别。

第四句

alert(global_sum);

解釋器繼續(xù)前進(jìn)铜幽,碰到了語(yǔ)句alert(global_sum);很簡(jiǎn)單,就是發(fā)出一個(gè)彈窗串稀,彈窗的內(nèi)容就是global_sum的值30除抛,當(dāng)我們點(diǎn)擊彈窗上的確定按鈕后,解釋器知道母截,這段代碼終于執(zhí)行完了到忽,它會(huì)打掃戰(zhàn)場(chǎng),把global_context微酬,context_stack等資源全部銷毀绘趋。

再遇閉包

現(xiàn)在,知道了上下文颗管,函數(shù)的scope屬性的知識(shí)后,我們就可以開(kāi)始學(xué)習(xí)閉包了滓走。讓我們將上面的js代碼改成這樣:

var  global_var1 = 10;
function  global_function1(parameter_a){
    var  local_var1 = 10 ;
   function local_function1(parameter_b){
        return parameter_b  + local_var1 + parameter_a + global_var1;
   }
   return   local_function1 ;
}
var global_sum = global_function1(10);
alert(global_sum(10));

這段代碼與原先的代碼最大的不同是垦江,在global_function1內(nèi)部,我們創(chuàng)建了一個(gè)函數(shù)local_function1搅方,并且將它作為返回值比吭。

當(dāng)解釋器執(zhí)行函數(shù)global_function1時(shí),仍然會(huì)為它創(chuàng)建執(zhí)行上下文姨涡,只不過(guò)此時(shí)execute_context.VO中多了一個(gè)函數(shù)屬性local_function1衩藤。然后,解釋器就會(huì)開(kāi)始執(zhí)行global_function1中的代碼涛漂。

我們直接從創(chuàng)建local_function1語(yǔ)句開(kāi)始分析赏表,看解釋器是怎么執(zhí)行的,閉包的所有秘密就隱藏在其中匈仗。

當(dāng)解釋器在execute_context中執(zhí)行創(chuàng)建local_function1時(shí)瓢剿,它仍然會(huì)將execute_context的Scope設(shè)置給函數(shù)local_function1的scope屬性,也就是這樣:

local_function1.scope = [ execute_context.Variable_Object,   global_context.Variable_Object ]

然后悠轩,解釋器碰到了返回語(yǔ)句间狂,把local_function1返回并賦值給了全局變量global_sum。此時(shí)global_context的VO中global_sum的值就是函數(shù)local_function1火架。

此時(shí)鉴象,函數(shù)global_function1已經(jīng)執(zhí)行完了忙菠,解釋器會(huì)怎么處理它的execute_context呢?

首先纺弊,解釋器會(huì)把execute_context從context_stack中彈出牛欢,但并不把它完全銷毀,而是保留了execute_context.Variable_Object對(duì)象俭尖,把它轉(zhuǎn)移到了另一塊堆內(nèi)存中氢惋。為什么不銷毀呢?因?yàn)檫€有對(duì)象引用著它呢稽犁。引用鏈如下:

這意味著什么呢焰望?這說(shuō)明,當(dāng)global_function1結(jié)束返回后已亥,它的形式參數(shù)parameter_a熊赖,局部變量local_var1以及局部函數(shù)local_function1都沒(méi)有銷毀,還仍然存在虑椎。這一點(diǎn)震鹉,與面向?qū)ο蟮恼Z(yǔ)言Java中的經(jīng)驗(yàn)完全不同,這也是閉包難以理解的根本所在捆姜。

下面我們的解釋器繼續(xù)執(zhí)行語(yǔ)句alert(global_sum(10));alert參數(shù)是對(duì)函數(shù)global_sum的調(diào)用传趾,global_sum的參數(shù)為10,我們知道函數(shù)global_sum的代碼是這樣的:

function local_function1(parameter_b){
    return parameter_b  + local_var1 + parameter_a + global_var1;
}

要執(zhí)行這個(gè)函數(shù)泥技,解釋器仍然會(huì)為它創(chuàng)建一個(gè)執(zhí)行上下文浆兰,我們姑且稱之為local_context2,這個(gè)對(duì)象的內(nèi)容是這樣的:

execute_context2 = {
   Variable_Object :{ 
           parameter_b:10,
           arguments:[10]              
    },
    Scope          :[execute_context2.Variable_Object, execute_context.Variable_Object, global_context.Variable_Object ],
    this           :undefined
}

這里我們重點(diǎn)看看Scope屬性珊豹,它的第一個(gè)元素毫無(wú)疑問(wèn)是execute_context2.Variable_Object簸呈,后面的元素是從local_function1.scope屬性中獲得的,它是在local_function1創(chuàng)建時(shí)所在的執(zhí)行上下文的Scope屬性決定的店茶。

創(chuàng)建的execute_context2壓入context_stack后蜕便,解釋器開(kāi)始執(zhí)行語(yǔ)句

return parameter_b  + local_var1 + parameter_a + global_var1;

對(duì)于該句中四個(gè)變量,解釋器確定它們的值的辦法一如既往的簡(jiǎn)單贩幻,首先在當(dāng)前執(zhí)行上下文(也就是execute_context2)的Scope的第一個(gè)元素中查找轿腺,第一個(gè)找不到就在第二個(gè)元素中查找,然后就是第三個(gè)段直,直至global_context.Variable_Object吃溅。

然后,解釋器就會(huì)將四個(gè)變量值相加后返回鸯檬。彈出execute_context2决侈,此時(shí)execute_context2已經(jīng)沒(méi)有對(duì)象引用著它,解釋器就把它銷毀了。

最后赖歌,alert函數(shù)會(huì)收到值40枉圃,然后發(fā)出一個(gè)彈窗,彈窗的內(nèi)容就是40庐冯。程序結(jié)束

說(shuō)到現(xiàn)在孽亲,啥是閉包啊展父?

簡(jiǎn)單講返劲,當(dāng)我們從函數(shù)global_function1中返回另一個(gè)函數(shù)local_function1時(shí),由于local_function1scope屬性中引用著為執(zhí)行global_function1創(chuàng)建的execute_context.Variable_Object對(duì)象栖茉,導(dǎo)致global_function1在執(zhí)行完畢后篮绿,它的execute_context.Variable_Object對(duì)象并不會(huì)被回收,此時(shí)我們稱函數(shù)local_function1是一個(gè)閉包吕漂,因?yàn)樗耸且粋€(gè)函數(shù)外亲配,還保存著創(chuàng)建它的執(zhí)行上下文的變量信息,使得我們?cè)谡{(diào)用它時(shí)惶凝,仍然能夠訪問(wèn)這些變量吼虎。

函數(shù)將創(chuàng)建它的上下文中的VO對(duì)象封閉包含在自己的scope屬性中,函數(shù)就變成了一個(gè)閉包苍鲜。從這個(gè)廣泛的意義上來(lái)說(shuō)思灰,global_function1也可以叫做閉包,因?yàn)樗膕cope內(nèi)部屬性也包含了創(chuàng)建它的全局上下文的變量信息混滔,也就是global_context.VO

推薦文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末官辈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子遍坟,更是在濱河造成了極大的恐慌,老刑警劉巖晴股,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愿伴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡电湘,警方通過(guò)查閱死者的電腦和手機(jī)隔节,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寂呛,“玉大人怎诫,你說(shuō)我怎么就攤上這事〈荆” “怎么了幻妓?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)劫拢。 經(jīng)常有香客問(wèn)我肉津,道長(zhǎng)强胰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任妹沙,我火速辦了婚禮偶洋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘距糖。我一直安慰自己玄窝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布悍引。 她就那樣靜靜地躺著恩脂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吗铐。 梳的紋絲不亂的頭發(fā)上东亦,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音唬渗,去河邊找鬼典阵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛镊逝,可吹牛的內(nèi)容都是我干的壮啊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撑蒜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼歹啼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起座菠,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狸眼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后浴滴,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拓萌,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年升略,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了微王。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡品嚣,死狀恐怖炕倘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翰撑,我是刑警寧澤罩旋,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響瘸恼,放射性物質(zhì)發(fā)生泄漏劣挫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一东帅、第九天 我趴在偏房一處隱蔽的房頂上張望压固。 院中可真熱鬧,春花似錦靠闭、人聲如沸帐我。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拦键。三九已至,卻和暖如春檩淋,著一層夾襖步出監(jiān)牢的瞬間芬为,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工蟀悦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留媚朦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓日戈,卻偏偏與公主長(zhǎng)得像询张,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浙炼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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