理解 JavaScript 作用域

簡介

JavaScript 有個特性稱為作用域报强。盡管對于很多開發(fā)新手來說,作用域的概念不容易理解拱燃,我會盡可能地從最簡單的角度向你解釋它們秉溉。理解作用域能讓你編寫更優(yōu)雅、錯誤更少的代碼碗誉,并能幫助你實現(xiàn)強大的設(shè)計模式召嘶。

什么是作用域?

作用域是你的代碼在運行時哮缺,各個變量弄跌、函數(shù)和對象的可訪問性。換句話說蝴蜓,作用域決定了你的代碼里的變量和其他資源在各個區(qū)域中的可見性碟绑。

為什么需要作用域俺猿?最小訪問原則

那么,限制變量的可見性格仲,不允許你代碼中所有的東西在任意地方都可用的好處是什么押袍?其中一個優(yōu)勢,是作用域為你的代碼提供了一個安全層級凯肋。計算機安全中谊惭,有個常規(guī)的原則是:用戶只能訪問他們當(dāng)前需要的東西。

想想計算機管理員吧侮东。他們在公司各個系統(tǒng)上擁有很多控制權(quán)圈盔,看起來甚至可以給予他們擁有全部權(quán)限的賬號。假設(shè)你有一家公司悄雅,擁有三個管理員驱敲,他們都有系統(tǒng)的全部訪問權(quán)限,并且一切運轉(zhuǎn)正常宽闲。但是突然發(fā)生了一點意外众眨,你的一個系統(tǒng)遭到惡意病毒攻擊。現(xiàn)在你不知道這誰出的問題了吧容诬?你這才意識到你應(yīng)該只給他們基本用戶的賬號娩梨,并且只在需要時賦予他們完全的訪問權(quán)。這能幫助你跟蹤變化并記錄每個人的操作览徒。這叫做最小訪問原則狈定。眼熟嗎?這個原則也應(yīng)用于編程語言設(shè)計习蓬,在大多數(shù)編程語言(包括 JavaScript)中稱為作用域纽什,接下來我們就要學(xué)習(xí)它。

在你的編程旅途中友雳,你會意識到作用域在你的代碼中可以提升性能稿湿,跟蹤 bug 并減少 bug。作用域還解決不同范圍的同名變量命名問題押赊。記住不要弄混作用域和上下文饺藤。它們是不同的特性。

JavaScript中的作用域

在 JavaScript 中有兩種作用域

全局作用域

局部作用域

當(dāng)變量定義在一個函數(shù)中時流礁,變量就在局部作用域中涕俗,而定義在函數(shù)之外的變量則從屬于全局作用域。每個函數(shù)在調(diào)用的時候會創(chuàng)建一個新的作用域神帅。

全局作用域

當(dāng)你在文檔中(document)編寫 JavaScript 時再姑,你就已經(jīng)在全局作用域中了。JavaScript 文檔中(document)只有一個全局作用域找御。定義在函數(shù)之外的變量會被保存在全局作用域中元镀。

// the scope is by default global

var?name?=?'Hammad';

全局作用域里的變量能夠在其他作用域中被訪問和修改绍填。

var?name?=?'Hammad';


console.log(name);?// logs 'Hammad'


function?logName()?{

????console.log(name);?// 'name' is accessible here and everywhere else

}


logName();?// logs 'Hammad'

局部作用域

定義在函數(shù)中的變量就在局部作用域中。并且函數(shù)在每次調(diào)用時都有一個不同的作用域栖疑。這意味著同名變量可以用在不同的函數(shù)中讨永。因為這些變量綁定在不同的函數(shù)中,擁有不同作用域遇革,彼此之間不能訪問卿闹。

// Global Scope

function?someFunction()?{

????// Local Scope ##1

????function?someOtherFunction()?{

????????// Local Scope ##2

????}

}


// Global Scope

function?anotherFunction()?{

????// Local Scope ##3

}

// Global Scope

塊語句

塊級聲明包括if和switch,以及for和while循環(huán)萝快,和函數(shù)不同锻霎,它們不會創(chuàng)建新的作用域。在塊級聲明中定義的變量從屬于該塊所在的作用域揪漩。

if?(true)?{

????// this 'if' conditional block doesn't create a new scope

????var?name?=?'Hammad';?// name is still in the global scope

}


console.log(name);?// logs 'Hammad'

ECMAScript 6 引入了let和const關(guān)鍵字旋恼。這些關(guān)鍵字可以代替var。

var?name?=?'Hammad';


let likes?=?'Coding';

const?skills?=?'Javascript and PHP';

和var關(guān)鍵字不同氢拥,let和const關(guān)鍵字支持在塊級聲明中創(chuàng)建使用局部作用域蚌铜。

if?(true)?{

????// this 'if' conditional block doesn't create a scope


????// name is in the global scope because of the 'var' keyword

????var?name?=?'Hammad';

????// likes is in the local scope because of the 'let' keyword

????let likes?=?'Coding';

????// skills is in the local scope because of the 'const' keyword

????const?skills?=?'JavaScript and PHP';

}


console.log(name);?// logs 'Hammad'

console.log(likes);?// Uncaught ReferenceError: likes is not defined

console.log(skills);?// Uncaught ReferenceError: skills is not defined

一個應(yīng)用中全局作用域的生存周期與該應(yīng)用相同。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在嫩海。

上下文

很多開發(fā)者經(jīng)常弄混作用域和上下文,似乎兩者是一個概念囚痴。但并非如此叁怪。作用域是我們上面講到的那些,而上下文通常涉及到你代碼某些特殊部分中的this值深滚。作用域指的是變量的可見性奕谭,而上下文指的是在相同的作用域中的this的值。我們當(dāng)然也可以使用函數(shù)方法改變上下文痴荐,這個之后我們再討論血柳。在全局作用域中,上下文總是 Window 對象生兆。

// logs: Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage…}

console.log(this);


function?logFunction()?{

????console.log(this);

}

// logs: Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage…}

// because logFunction() is not a property of an object

logFunction();

如果作用域定義在一個對象的方法中难捌,上下文就是這個方法所在的那個對象。

class?User?{

????logName()?{

????????console.log(this);

????}

}


(new?User).logName();?// logs User {}

(new User).logName()是創(chuàng)建對象關(guān)聯(lián)到變量并調(diào)用logName方法的一種簡便形式鸦难。通過這種方式你并不需要創(chuàng)建一個新的變量根吁。

你可能注意到一點,就是如果你使用new關(guān)鍵字調(diào)用函數(shù)時上下文的值會有差異合蔽。上下文會設(shè)置為被調(diào)用的函數(shù)的實例击敌。考慮一下上面的這個例子拴事,用new關(guān)鍵字調(diào)用的函數(shù)沃斤。

function?logFunction()?{

????console.log(this);

}


new?logFunction();?// logs logFunction {}

當(dāng)在嚴(yán)格模式(strict mode)中調(diào)用函數(shù)時圣蝎,上下文默認(rèn)是 undefined。

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

為了解決掉我們從上面學(xué)習(xí)中會出現(xiàn)的各種困惑衡瓶,“執(zhí)行環(huán)境(context)”這個詞中的“環(huán)境(context)”指的是作用域而并非上下文捅彻。這是一個怪異的命名約定,但由于 JavaScript 的文檔如此鞍陨,我們只好也這樣約定步淹。

JavaScript 是一種單線程語言,所以它同一時間只能執(zhí)行單個任務(wù)诚撵。其他任務(wù)排列在執(zhí)行環(huán)境中缭裆。當(dāng) JavaScript 解析器開始執(zhí)行你的代碼,環(huán)境(作用域)默認(rèn)設(shè)為全局寿烟。全局環(huán)境添加到你的執(zhí)行環(huán)境中澈驼,事實上這是執(zhí)行環(huán)境里的第一個環(huán)境。

之后筛武,每個函數(shù)調(diào)用都會添加它的環(huán)境到執(zhí)行環(huán)境中缝其。無論是函數(shù)內(nèi)部還是其他地方調(diào)用函數(shù),都會是相同的過程徘六。

每個函數(shù)都會創(chuàng)建它自己的執(zhí)行環(huán)境内边。

當(dāng)瀏覽器執(zhí)行完環(huán)境中的代碼,這個環(huán)境會從執(zhí)行環(huán)境中彈出待锈,執(zhí)行環(huán)境中當(dāng)前環(huán)境的狀態(tài)會轉(zhuǎn)移到父級環(huán)境漠其。瀏覽器總是先執(zhí)行在執(zhí)行棧頂?shù)膱?zhí)行環(huán)境(事實上就是你代碼最里層的作用域)。

全局環(huán)境只能有一個竿音,函數(shù)環(huán)境可以有任意多個和屎。

執(zhí)行環(huán)境有兩個階段:創(chuàng)建和執(zhí)行。

創(chuàng)建階段

第一階段是創(chuàng)建階段春瞬,是函數(shù)剛被調(diào)用但代碼并未執(zhí)行的時候柴信。創(chuàng)建階段主要發(fā)生了 3 件事。

創(chuàng)建變量對象

創(chuàng)建作用域鏈

設(shè)置上下文(this)的值

變量對象

變量對象(Variable Object)也稱為活動對象(activation object)宽气,包含所有變量随常、函數(shù)和其他在執(zhí)行環(huán)境中定義的聲明。當(dāng)函數(shù)調(diào)用時抹竹,解析器掃描所有資源线罕,包括函數(shù)參數(shù)、變量和其他聲明窃判。當(dāng)所有東西裝填進一個對象钞楼,這個對象就是變量對象。

'variableObject':?{

????// contains function arguments, inner variable and function declarations

}

作用域鏈

在執(zhí)行環(huán)境創(chuàng)建階段袄琳,作用域鏈在變量對象之后創(chuàng)建询件。作用域鏈包含變量對象燃乍。作用域鏈用于解析變量。當(dāng)解析一個變量時宛琅,JavaScript 開始從最內(nèi)層沿著父級尋找所需的變量或其他資源刻蟹。作用域鏈包含自己執(zhí)行環(huán)境以及所有父級環(huán)境中包含的變量對象。

'scopeChain':?{

????// contains its own variable object and other variable objects of the parent execution contexts

}

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

執(zhí)行環(huán)境可以用下面抽象對象表示:

executionContextObject?=?{

????'scopeChain':?{},?// contains its own variableObject and other variableObject of the parent execution contexts

????'variableObject':?{},?// contains function arguments, inner variable and function declarations

????'this':?valueOfThis

}

代碼執(zhí)行階段

執(zhí)行環(huán)境的第二個階段就是代碼執(zhí)行階段嘿辟,進行其他賦值操作并且代碼最終被執(zhí)行舆瘪。

詞法作用域

詞法作用域的意思是在函數(shù)嵌套中,內(nèi)層函數(shù)可以訪問父級作用域的變量等資源红伦。這意味著子函數(shù)詞法綁定到了父級執(zhí)行環(huán)境英古。詞法作用域有時和靜態(tài)作用域有關(guān)。

function?grandfather()?{

????var?name?=?'Hammad';

????// likes is not accessible here

????function?parent()?{

????????// name is accessible here

????????// likes is not accessible here

????????function?child()?{

????????????// Innermost level of the scope chain

????????????// name is also accessible here

????????????var?likes?=?'Coding';

????????}

????}

}

你可能注意到了詞法作用域是向前的昙读,意思是子執(zhí)行環(huán)境可以訪問name召调。但不是由父級向后的,意味著父級不能訪問likes蛮浑。這也告訴了我們唠叛,在不同執(zhí)行環(huán)境中同名變量優(yōu)先級在執(zhí)行棧由上到下增加。一個變量和另一個變量同名沮稚,內(nèi)層函數(shù)(執(zhí)行棧頂?shù)沫h(huán)境)有更高的優(yōu)先級艺沼。

閉包

閉包的概念和我們剛學(xué)習(xí)的詞法作用域緊密相關(guān)。當(dāng)內(nèi)部函數(shù)試著訪問外部函數(shù)的作用域鏈(詞法作用域之外的變量)時產(chǎn)生閉包壮虫。閉包包括它們自己的作用域鏈澳厢、父級作用域鏈和全局作用域。

閉包不僅能訪問外部函數(shù)的變量囚似,也能訪問外部函數(shù)的參數(shù)。

即使函數(shù)已經(jīng)return线得,閉包仍然能訪問外部函數(shù)的變量饶唤。這意味著return的函數(shù)允許持續(xù)訪問外部函數(shù)的所有資源。

當(dāng)你的外部函數(shù)return一個內(nèi)部函數(shù)贯钩,調(diào)用外部函數(shù)時return的函數(shù)并不會被調(diào)用募狂。你必須先用一個單獨的變量保存外部函數(shù)的調(diào)用,然后將這個變量當(dāng)做函數(shù)來調(diào)用角雷』銮睿看下面這個例子:

function?greet()?{

????name?=?'Hammad';

????return?function?()?{

????????console.log('Hi '?+?name);

????}

}


greet();?// nothing happens, no errors


// the returned function from greet() gets saved in greetLetter

greetLetter?=?greet();


// calling greetLetter calls the returned function from the greet() function

greetLetter();?// logs 'Hi Hammad'

值得注意的是,即使在greet函數(shù)return后勺三,greetLetter函數(shù)仍可以訪問greet函數(shù)的name變量雷滚。如果不使用變量賦值來調(diào)用greet函數(shù)return的函數(shù),一種方法是使用()兩次()()吗坚,如下所示:

function?greet()?{

????name?=?'Hammad';

????return?function?()?{

????????console.log('Hi '?+?name);

????}

}


greet()();?// logs 'Hi Hammad'

共有作用域和私有作用域

在許多其他編程語言中祈远,你可以通過 public呆万、private 和 protected 作用域來設(shè)置類中變量和方法的可見性〕捣荩看下面這個 PHP 的例子

// Public Scope

public?$property;

public?function?method()?{

??// ...

}


// Private Sccpe

private?$property;

private?function?method()?{

??// ...

}


// Protected Scope

protected?$property;

protected?function?method()?{

??// ...

}

將函數(shù)從公有(全局)作用域中封裝谋减,使它們免受攻擊。但在 JavaScript 中扫沼,沒有 共有作用域和私有作用域出爹。然而我們可以用閉包實現(xiàn)這一特性。為了使每個函數(shù)從全局中分離出去缎除,我們要將它們封裝進如下所示的函數(shù)中:

(function?()?{

??// private scope

})();

函數(shù)結(jié)尾的括號告訴解析器立即執(zhí)行此函數(shù)严就。我們可以在其中加入變量和函數(shù),外部無法訪問伴找。但如果我們想在外部訪問它們盈蛮,也就是說我們希望它們一部分是公開的,一部分是私有的技矮。我們可以使用閉包的一種形式抖誉,稱為模塊模式(Module Pattern),它允許我們用一個對象中的公有作用域和私有作用域來劃分函數(shù)衰倦。

模塊模式

模塊模式如下所示:

var?Module?=?(function()?{

????function?privateMethod()?{

????????// do something

????}


????return?{

????????publicMethod:?function()?{

????????????// can call privateMethod();

????????}

????};

})();

Module 的return語句包含了我們的公共函數(shù)袒炉。私有函數(shù)并沒有被return。函數(shù)沒有被return確保了它們在 Module 命名空間無法訪問樊零。但我們的共有函數(shù)可以訪問我們的私有函數(shù)我磁,方便它們使用有用的函數(shù)、AJAX 調(diào)用或其他東西驻襟。

Module.publicMethod();?// works

Module.privateMethod();?// Uncaught ReferenceError: privateMethod is not defined

一種習(xí)慣是以下劃線作為開始命名私有函數(shù)夺艰,并返回包含共有函數(shù)的匿名對象。這使它們在很長的對象中很容易被管理沉衣。向下面這樣:

var?Module?=?(function?()?{

????function?_privateMethod()?{

????????// do something

????}

????function?publicMethod()?{

????????// do something

????}

????return?{

????????publicMethod:?publicMethod,

????}

})();

立即執(zhí)行函數(shù)表達式(IIFE)

另一種形式的閉包是立即執(zhí)行函數(shù)表達式(Immediately-Invoked Function Expression郁副,IIFE)。這是一種在 window 上下文中自調(diào)用的匿名函數(shù)豌习,也就是說this的值是window存谎。它暴露了一個單一全局接口用來交互。如下所示:

(function(window)?{

????// do anything

})(this);

使用 .call()肥隆, .apply() 和 .bind() 改變上下文

Call 和 Apply 函數(shù)來改變函數(shù)調(diào)用時的上下文既荚。這帶給你神奇的編程能力(和終極統(tǒng)治世界的能力)。你只需要使用 call 和 apply 函數(shù)并把上下文當(dāng)做第一個參數(shù)傳入栋艳,而不是使用括號來調(diào)用函數(shù)恰聘。函數(shù)自己的參數(shù)可以在上下文后面?zhèn)魅搿?/p>

function?hello()?{

????// do something...

}


hello();?// the way you usually call it

hello.call(context);?// here you can pass the context(value of this) as the first argument

hello.apply(context);?// here you can pass the context(value of this) as the first argument

.call()和.apply()的區(qū)別是 Call 中其他參數(shù)用逗號分隔傳入,而 Apply 允許你傳入一個參數(shù)數(shù)組。

function?introduce(name,?interest)?{

????console.log('Hi! I'm?'+ name +'?and?I?like?'+ interest +'.');

????console.log('The value of?this?is?'+ this +'.')

}


introduce('Hammad', 'Coding'); // the way you usually call it

introduce.call(window, 'Batman', 'to?save?Gotham'); // pass the arguments one by one after the contextt

introduce.apply('Hi', ['Bruce?Wayne', 'businesses']); // pass the arguments in an array after the context


// Output:

// Hi! I'm?Hammad?and?I?like?Coding.

// The value of this is [object Window].

// Hi! I'm Batman and I like to save Gotham.

// The value of this is [object Window].

// Hi! I'm Bruce Wayne and I like businesses.

// The value of this is Hi.

Call 比 Apply 的效率高一點憨琳。

下面這個例子列舉文檔中所有項目诫钓,然后依次在控制臺打印出來。

????

????Things?to?learn

????

Things?to?Learn?to?Rule?the?World

????

    ????????

  • Learn?PHP
  • ????????

  • Learn?Laravel
  • ????????

  • Learn?JavaScript
  • ????????

  • Learn?VueJS
  • ????????

  • Learn?CLI
  • ????????

  • Learn?Git
  • ????????

  • Learn?Astral?Projection

  • ????

    ????????// Saves a NodeList of all list items on the page in listItems

    ????????var?listItems?=?document.querySelectorAll('ul li');

    ????????// Loops through each of the Node in the listItems NodeList and logs its content

    ????????for?(var?i?=?0;?i?<?listItems.length;?i++)?{

    ??????????(function?()?{

    ????????????console.log(this.innerHTML);

    ??????????}).call(listItems[i]);

    ????????}


    ????????// Output logs:

    ????????// Learn PHP

    ????????// Learn Laravel

    ????????// Learn JavaScript

    ????????// Learn VueJS

    ????????// Learn CLI

    ????????// Learn Git

    ????????// Learn Astral Projection


    HTML文檔中僅包含一個無序列表篙螟。JavaScript 從 DOM 中選取它們菌湃。列表項會被從頭到尾循環(huán)一遍。在循環(huán)時遍略,我們把列表項的內(nèi)容輸出到控制臺惧所。

    輸出語句包含在由括號包裹的函數(shù)中,然后調(diào)用call函數(shù)绪杏。相應(yīng)的列表項傳入 call 函數(shù)下愈,確保控制臺輸出正確對象的 innerHTML蕾久。

    對象可以有方法势似,同樣函數(shù)對象也可以有方法。事實上僧著,JavaScript 函數(shù)有 4 個內(nèi)置方法:

    Function.prototype.apply()

    Function.prototype.bind() (Introduced in ECMAScript 5 (ES5))

    Function.prototype.call()

    Function.prototype.toString()

    Function.prototype.toString()返回函數(shù)代碼的字符串表示履因。

    到現(xiàn)在為止,我們討論了.call()盹愚、.apply()和toString()栅迄。與 Call 和 Apply 不同,Bind 并不是自己調(diào)用函數(shù)皆怕,它只是在函數(shù)調(diào)用之前綁定上下文和其他參數(shù)毅舆。在上面提到的例子中使用 Bind:

    (function?introduce(name,?interest)?{

    ????console.log('Hi! I'm?'+ name +'?and?I?like?'+ interest +'.');

    ????console.log('The value of?this?is?'+ this +'.')

    }).bind(window, 'Hammad', 'Cosmology')();


    // logs:

    // Hi! I'm?Hammad?and?I?like?Cosmology.

    // The value of this is [object Window].

    Bind 像call函數(shù)一樣用逗號分隔其他傳入?yún)?shù),不像apply那樣用數(shù)組傳入?yún)?shù)愈腾。

    結(jié)論

    這些概念是 JavaScript 的基礎(chǔ)涤久,如果你想鉆研更深的話澈缺,理解這些很重要姻檀。我希望你對 JavaScript 作用域及相關(guān)概念有了更好地理解皂甘。如果有東西不清楚作谭,可以在評論區(qū)提問苍凛。

    作用域常伴你的代碼左右箍铭,享受編碼螟炫!

    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
    • 序言:七十年代末赁豆,一起剝皮案震驚了整個濱河市仅醇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌魔种,老刑警劉巖析二,帶你破解...
      沈念sama閱讀 207,113評論 6 481
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡叶摄,警方通過查閱死者的電腦和手機属韧,發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 88,644評論 2 381
    • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛤吓,“玉大人宵喂,你說我怎么就攤上這事』岚粒” “怎么了锅棕?”我有些...
      開封第一講書人閱讀 153,340評論 0 344
    • 文/不壞的土叔 我叫張陵,是天一觀的道長淌山。 經(jīng)常有香客問我裸燎,道長,這世上最難降的妖魔是什么泼疑? 我笑而不...
      開封第一講書人閱讀 55,449評論 1 279
    • 正文 為了忘掉前任德绿,我火速辦了婚禮,結(jié)果婚禮上退渗,老公的妹妹穿的比我還像新娘移稳。我一直安慰自己,他們只是感情好氓辣,可當(dāng)我...
      茶點故事閱讀 64,445評論 5 374
    • 文/花漫 我一把揭開白布秒裕。 她就那樣靜靜地躺著,像睡著了一般钞啸。 火紅的嫁衣襯著肌膚如雪几蜻。 梳的紋絲不亂的頭發(fā)上,一...
      開封第一講書人閱讀 49,166評論 1 284
    • 那天体斩,我揣著相機與錄音梭稚,去河邊找鬼。 笑死絮吵,一個胖子當(dāng)著我的面吹牛弧烤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹬敲,決...
      沈念sama閱讀 38,442評論 3 401
    • 文/蒼蘭香墨 我猛地睜開眼暇昂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伴嗡?” 一聲冷哼從身側(cè)響起急波,我...
      開封第一講書人閱讀 37,105評論 0 261
    • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘪校,沒想到半個月后澄暮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體名段,經(jīng)...
      沈念sama閱讀 43,601評論 1 300
    • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點故事閱讀 36,066評論 2 325
    • 正文 我和宋清朗相戀三年泣懊,在試婚紗的時候發(fā)現(xiàn)自己被綠了伸辟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
      茶點故事閱讀 38,161評論 1 334
    • 序言:一個原本活蹦亂跳的男人離奇死亡馍刮,死狀恐怖信夫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渠退,我是刑警寧澤忙迁,帶...
      沈念sama閱讀 33,792評論 4 323
    • 正文 年R本政府宣布,位于F島的核電站碎乃,受9級特大地震影響姊扔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梅誓,卻給世界環(huán)境...
      茶點故事閱讀 39,351評論 3 307
    • 文/蒙蒙 一恰梢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梗掰,春花似錦嵌言、人聲如沸。這莊子的主人今日做“春日...
      開封第一講書人閱讀 30,352評論 0 19
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至埂陆,卻和暖如春苛白,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背焚虱。 一陣腳步聲響...
      開封第一講書人閱讀 31,584評論 1 261
    • 我被黑心中介騙來泰國打工购裙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹃栽。 一個月前我還...
      沈念sama閱讀 45,618評論 2 355
    • 正文 我出身青樓躏率,卻偏偏與公主長得像,于是被迫代替她去往敵國和親民鼓。 傳聞我的和親對象是個殘疾皇子薇芝,可洞房花燭夜當(dāng)晚...
      茶點故事閱讀 42,916評論 2 344

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