構(gòu)造函數(shù)與原型(鏈)

?了解構(gòu)造函數(shù)和原型鏈之前爸黄,我們先復(fù)習(xí)一下關(guān)于引用類型的知識搁凸。

# 引用類型

? 在OO語言中這種數(shù)據(jù)結(jié)構(gòu)通常稱作“類”萌朱,在JS中這么稱呼不太準(zhǔn)確屠阻。是一種用于將數(shù)據(jù)和功能組織在一起的數(shù)據(jù)結(jié)構(gòu)红省。引用類型的最大特征就是,使用一個指針來指向數(shù)據(jù)真正存儲的位置国觉,而指針與數(shù)據(jù)之間并沒有強(qiáng)關(guān)聯(lián)關(guān)系吧恃。常說的對象,是Object引用類型(以下簡稱Object類型)的實(shí)例麻诀。
? JavaScript中引用類型主要有以下幾種:關(guān)于數(shù)組和對象更詳細(xì)請閱讀引用類型之「對象/數(shù)組」

(1)Object類型:使用鍵值對來存放數(shù)據(jù)的一種數(shù)據(jù)結(jié)構(gòu)痕寓,通常判斷方法有:實(shí)例.constructor === Object傲醉,實(shí)例 instanceof Object返回true,而typeof 實(shí)例 === 'object'

(2)Array類型:數(shù)組中的每一項(xiàng)可以存儲不同類型的數(shù)據(jù)呻率。使用下標(biāo)來取硬毕。實(shí)例.constructor === Array實(shí)例 instanceof Array返回true礼仗, 而typeof 實(shí)例 === 'array'

(3)Date類型:日期類型吐咳,通常使用UTC時間格式。new Date()接收毫秒?yún)?shù)元践。當(dāng)直接傳入字符串如2020, 4, 10時韭脊,其實(shí)是在Date()內(nèi)模擬了Date.UTC()Date.parse()的字符串參數(shù)格式是'月/日/年')進(jìn)行了解析,變成毫秒數(shù)后再傳遞給Date()構(gòu)造函數(shù)的卢厂。注意UTC()方法中的月份從0開始乾蓬,因此該例子是2020年5月10日(parse()無此問題)。

(4)RegExp類型:正則類型慎恒,語法:var exp = /pattern/flag任内。pattern定義使用^符號開始,$符號結(jié)束融柬。flag中g表示全查詢死嗦,i表示不區(qū)分大小寫,m表示多行查詢粒氧。

(5)Function類型:函數(shù)類型越除。JS中:函數(shù)是對象,函數(shù)名是指針外盯。復(fù)制函數(shù)名只是新增了一個指向函數(shù)對象的指針摘盆。當(dāng)我們把函數(shù)當(dāng)做值在別的函數(shù)中進(jìn)行傳遞時,使用的是函數(shù)名傳遞饱苟,也就是說只是把函數(shù)對象的地址告訴了宿主調(diào)用函數(shù)孩擂。但是如果在傳遞時我們給參數(shù)函數(shù)名增加了括號,此時表示將函數(shù)對象進(jìn)行執(zhí)行后箱熬,把返回值傳遞給宿主調(diào)用函數(shù)类垦。此外,函數(shù)中內(nèi)置有arguments對象和this對象城须,前者存放函數(shù)的參數(shù)對象以及callee(指向該函數(shù)名)和caller(指向調(diào)用該函數(shù)的宿主函數(shù))等信息蚤认,而后者存放的是運(yùn)行該函數(shù)時函數(shù)所在的執(zhí)行環(huán)境。當(dāng)我們需要修改或指定函數(shù)執(zhí)行環(huán)境時糕伐,可以使用call()apply()方法砰琢。前者接收多個參數(shù),后者接受兩個參數(shù),第一個參數(shù)均表示要調(diào)用該函數(shù)的執(zhí)行環(huán)境如window氯析、某個私有域等亏较,該作用域近在本次函數(shù)運(yùn)行時有效。bind()方法用于將該函數(shù)的執(zhí)行環(huán)境長期綁定到某個環(huán)境對象中掩缓,注意bind()不改變當(dāng)前函數(shù)的運(yùn)行環(huán)境雪情,而是返回?fù)碛薪壎ōh(huán)境對象的新函數(shù)。

(6)基本包裝類型:String類型你辣,Number類型巡通,Boolean類型。它們的特點(diǎn)是在執(zhí)行過程中自動創(chuàng)建舍哄,且生命周期僅存在于代碼執(zhí)行的那一瞬間宴凉,運(yùn)行結(jié)束即銷毀。這也是為什么作為值類型的String卻擁有slice()表悬、substring()弥锄、substr()indexOf()蟆沫、lastIndexOf()籽暇、trim()等屬性方法的原因,這些方法都繼承于String類型的原型方法饭庞。

(7)單體內(nèi)置對象:Global對象戒悠、Math對象。Global對象是JS中的“兜底兒對象”舟山,其實(shí)并沒有什么全局變量全局方法绸狐,它們只不過都是Global對象的屬性和方法罷了,在各大Web瀏覽器中累盗,將Global對象作為window對象的一部分加以實(shí)現(xiàn)(window還有別的任務(wù))寒矿,所以通常使用window來調(diào)用或直接省略window。比較經(jīng)典的幾個方法是encodeURI若债、isNaN()劫窒、parseInt()eval()拆座、構(gòu)造函數(shù)Object構(gòu)造函數(shù)Function冠息、構(gòu)造函數(shù)SybtaxError挪凑、構(gòu)造函數(shù)TypeError,而屬性也有undefined逛艰、NaN等躏碳。而Math對象中保存了數(shù)學(xué)計(jì)算中可能會用到的一些特殊值和常用方法,如Math.E(自然對數(shù)底數(shù))散怖、Math.PI菇绵、Math.SQRT(平方根)等肄渗、min()max()咬最、ceil()向上舍入翎嫡、floor()向下舍入round()四舍五入永乌、random()大于0小于1的隨機(jī)數(shù)惑申、abs()絕對值pow(n, p)n的p次冪翅雏、cos()余弦值等圈驼。


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

? 一般用來創(chuàng)建特定類型的對象。構(gòu)造函數(shù)分為兩種:原生構(gòu)造函數(shù)和自定義構(gòu)造函數(shù)望几。在實(shí)例中绩脆,一般使用 實(shí)例.constructor來獲取構(gòu)造函數(shù)名。注意JS慣例規(guī)定構(gòu)造函數(shù)首字母要大寫橄抹。構(gòu)造函數(shù)是JavaScript被定義為 OO (Object Oriented)語言的重要因素之一靴迫,也是JS實(shí)現(xiàn)繼承的重要手段

  • 原生構(gòu)造函數(shù)
    最常見原生構(gòu)造函數(shù)是Object、Array害碾、Date矢劲,當(dāng)然還有RegExp、Function等等慌随。
    (1)Object: 用于創(chuàng)建Object類型的實(shí)例芬沉,即對象。用法:var obj = new Object()
    (2)Array: 用于創(chuàng)建Array類型的實(shí)例阁猜,即數(shù)組丸逸。用法var arr = new Array()
    (3)Date: 用于創(chuàng)建Date類型的實(shí)例,即日期剃袍。用法var date = new Date()

  • 自定義構(gòu)造函數(shù)
    (1)一個自定義構(gòu)造函數(shù)實(shí)踐

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function() {
    alert(this.name)
  }
}
var person1 = new Person('Nic', '22', 'softEngineer')
var person2 = new Person('Xud', '16', 'teacher')

? new操作符主要執(zhí)行的邏輯包括:1)創(chuàng)建了一個新對象黄刚;2)將構(gòu)造函數(shù)的作用域(this)賦給新對象;3)執(zhí)行構(gòu)造函數(shù)中的邏輯民效;4)返回新對象腹纳。

(2)構(gòu)造函數(shù)和函數(shù)
? 主要的區(qū)別就是調(diào)用方式不同啃勉。構(gòu)造函數(shù)其實(shí)也是函數(shù)。任何函數(shù)使用new操作符來調(diào)用,就可以作為構(gòu)造函數(shù)來使用象缀,任何構(gòu)造函數(shù)直接函數(shù)名調(diào)用薪捍,那它和普通函數(shù)也就沒有區(qū)別藐鹤。構(gòu)造函數(shù)同樣也有call()apply()方法鳍置,可以根據(jù)需要改變它的執(zhí)行環(huán)境。

(3)構(gòu)造函數(shù)和工廠函數(shù)
? 以對象為例,工廠函數(shù)旨在在函數(shù)內(nèi)部new一個Object實(shí)例章鲤,根據(jù)人參處理對象屬性并return出該對象摊灭,運(yùn)行工廠函數(shù)后實(shí)實(shí)在在的從無到有的創(chuàng)建了一個新的對象并返回。
? 而自定義構(gòu)造函數(shù)則是根據(jù)需要的數(shù)據(jù)結(jié)構(gòu)先定義好一個構(gòu)造模板败徊,在需要的地方直接使用new來實(shí)例化這個構(gòu)造函數(shù)而非實(shí)時實(shí)例化Object帚呼,且這個過程不需要手動return,因?yàn)樵趫?zhí)行實(shí)例化的時候?qū)嵗詣泳蛽碛辛藰?gòu)造函數(shù)所擁有的實(shí)例屬性和原型屬性集嵌。

(4)B芗贰!根欧!使用new操作符來實(shí)例化構(gòu)造函數(shù)時怜珍,每個屬性和方法都要重新創(chuàng)建一遍,無論是值類型還是引用類型凤粗。從而保證了每次創(chuàng)建出來的實(shí)例都是互相獨(dú)立的酥泛。但我們知道,對一個相同的方法進(jìn)行多次定義是不必要的嫌拣,因此通常建議不在構(gòu)造函數(shù)中定義方法柔袁,而是定義在原型對象中。


# 原型對象异逐、原型

? 原型對象共享于所有實(shí)例中捶索,這為實(shí)現(xiàn)繼承創(chuàng)造了天然的條件。下文將原型對象灰瞻,原型指針腥例,實(shí)例原型指針等概念區(qū)分的比較精確,實(shí)際上在稱呼時常有混淆酝润,需要注意觀察稱呼時表示的是誰的屬性燎竖,就能理解是什么意思。

(1)只要創(chuàng)建了一個新函數(shù)要销,就會根據(jù)一組特定規(guī)則為該函數(shù)創(chuàng)建一個prototype(原型)屬性构回,它是一個指針,指向函數(shù)的原型對象疏咐。默認(rèn)的原型對象會自動獲取一個constructor(構(gòu)造函數(shù))屬性纤掸,該屬性指向prototype所在函數(shù)對象的指針(即函數(shù)名)。
? 拿上面的構(gòu)造函數(shù)來舉例:Person.prototype.constructor指向了Person浑塞。

(2)除constructor屬性是自動擁有外借跪,我們還能夠?yàn)槠涮砑幼远x的原型屬性,這些原型屬性被所有的實(shí)例共享缩举,假設(shè)構(gòu)造函數(shù)Person 有兩個實(shí)例 person1 和 person2,它們的指向關(guān)系如下:

構(gòu)造函數(shù)、實(shí)例仅孩、原型與原型對象的關(guān)系

1)理解一點(diǎn):Person.prototype是一個指針托猩,而圖中的 Person Prototype是 Person的原型對象,在JS中辽慕,正是用Person.prototype來訪問和設(shè)置該原型對象的京腥。原型對象上的屬性被稱為構(gòu)造函數(shù)或?qū)嵗?em>原型屬性。而構(gòu)造函數(shù)和實(shí)例自身的屬性稱為實(shí)例屬性溅蛉。
2)圖中實(shí)例person1和實(shí)例person2中的 [[Prototype]] 是在實(shí)例化構(gòu)造函數(shù)時公浪,每個實(shí)例都會自動獲取的一個內(nèi)部指針屬性,ECMA-262第5版將他表示為[[Prototype]]船侧,在各大Web瀏覽器中欠气,將這個內(nèi)部屬性表示為__proto__,可以稱為實(shí)例原型指針镜撩。在JS中预柒,執(zhí)行hasOwnProperty()查找對象某個屬性時,當(dāng)實(shí)例屬性里沒有需要繼續(xù)查找原型屬性時袁梗,就是通過該屬性找到的原型對象并訪問其屬性的宜鸯。
3)[[Prototype]]__proto__,是實(shí)例與原型對象之間的關(guān)系遮怜,它與構(gòu)造函數(shù)并沒有直接關(guān)系淋袖。
4)圖中可以看出,實(shí)例.constructor獲取到構(gòu)造函數(shù)名的原因锯梁,正式因?yàn)橥ㄟ^__proto__這個指針找到了共享在原型對象中的constructor屬性即碗,而該屬性的值正是該原型對象的構(gòu)造函數(shù)名。
5)原型對象自身是一個數(shù)據(jù)結(jié)構(gòu)存放在內(nèi)存中涝桅,構(gòu)造函數(shù)通過prototype指針屬性來訪問拜姿,而實(shí)例通過__proto__指針屬性來訪問。這形成了一個三角關(guān)系

Person.prototype === person1.__proto__ === person2.__proto__
三角關(guān)系

(3)新創(chuàng)建一個函數(shù)時默認(rèn)會生成它的原型對象冯遂,我們可以通過構(gòu)造函數(shù)的prototype屬性或任意一個實(shí)例的__proto__(通常用前者)來給原型對象中添加和刪除原型屬性蕊肥,這些屬性的最大特征就是在所有的實(shí)例中共享。但某個屬性是值類型時蛤肌,如果不想共享可以在實(shí)例定義來屏蔽原型屬性壁却;當(dāng)某個原型屬性是引用類型時,某個實(shí)例對該屬性的修改裸准,將會實(shí)時影響其他實(shí)例展东,畢竟這些屬性只是保存了引用類型的地址。為了規(guī)避這個問題炒俱,可以將所有除方法外的引用類型屬性定義在夠造函數(shù)中即可盐肃。
? 通常設(shè)置原型屬性會使用Person.prototype來一個個的添加爪膊,這樣不會重寫protorype指針的指向。當(dāng)使用字面量法操作原型對象時砸王,即如下:

function Person() {}
var person = new Person();
// 使用字面量法修改原型對象上的屬性
Person.prototype = {
  constructor: Person, // 見下方解釋
  name: 'Nic',
  age: '22',
  job: 'Soft Engineer',
  sayName: function() {
    alert(this.name)
  }
}
alert(person.name); // 'Nic'

M剖ⅰ!谦铃!需要警惕的是耘成,這種方式雖然很方便很實(shí)用,但實(shí)質(zhì)上是給Person.prototype重新賦值給新定義的對象驹闰,由于指針的指向發(fā)生了改變瘪菌,該原型指針已經(jīng)切斷了和創(chuàng)建函數(shù)時默認(rèn)的原型對象的關(guān)系,也就是說嘹朗,重寫了原型對象师妙。它將無法正確的獲取默認(rèn)原型對象上constructor指向值,而變成什么骡显?
? 把等號后面的內(nèi)容單獨(dú)看疆栏,其實(shí)就是使用字面量法創(chuàng)建的一個Object類型的實(shí)例,那么它的構(gòu)造器應(yīng)該是 Object惫谤,即Person.prototype.constructor === Object!!!
? 為了修正為Person.prototype.constructor === Person壁顶,我們可以重寫字面量定義里的constructor屬性為 Person。如上代碼所示溜歪。

? 另外若专,從該案例中可以發(fā)現(xiàn),雖然先執(zhí)行了實(shí)例化蝴猪,在重寫Person的原型调衰,實(shí)例依然能正確獲取原型屬性,這歸功于原型具有動態(tài)性自阱,也就是prototype指針適用于引用類型的特性嚎莉。


# 原型鏈、繼承

? 上一個例子中沛豌,在沒有重寫constructor屬性之前趋箩,細(xì)心的你可能發(fā)現(xiàn)這個結(jié)構(gòu)其實(shí)就是把 Person 的protorype指針指向了Object類型的一個實(shí)例上,而由字面量定義的對象實(shí)例加派,也有prototype指針屬性和原型對象叫确,那么就可以得到如下信息:

person.__proto__.__proto__.constructor === Object

這里所出現(xiàn)的兩個__proto__指針屬性,形成了原型對象上的鏈?zhǔn)秸{(diào)用芍锦,我們稱之為原型鏈竹勉。

實(shí)現(xiàn)繼承的主要方法是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法,其主要思想是重寫一個引用類型的原型對象娄琉,使其等于另一個類型的實(shí)例次乓。

(1)一個實(shí)現(xiàn)繼承的實(shí)踐

function Super() {
  this.sex = 'male'
}

Super.prototype.getSex = function() {
  return this.sex
}

function Sub() {
  this.hobby= 'runing'
}

// 重寫Sub構(gòu)造函數(shù)的prototype指針吓歇,利用原型鏈實(shí)現(xiàn)繼承
Sub.prototype = new Super()

Sub.prototype.getName = function() {
  return this.name
}

var person = new Sub()

alert(person.getSex())  // male

? 這段代碼中,person是構(gòu)造函數(shù)Sub的實(shí)例票腰,但Sub構(gòu)造函數(shù)中并沒有getSex()這個實(shí)例方法照瘾,因此會去查找Sub的原型屬性,而案例中把Sub的默認(rèn)原型對象重寫成了Super的實(shí)例丧慈,而Super的實(shí)例可以通過__proto__指針取到Super原型對象中的getSex()方法,因此主卫,輸出了male

? 我們把上例中實(shí)現(xiàn)繼承的關(guān)鍵代碼拆開逃默,可得到如下描述

var superObj = new Super()
alert(superObj.sex); // 'male'
alert(superObj.getSex()); // 'male'

Sub.prototype = superObj
alert(Sub.sex); // 'male'
alert(Sub.getSex()); // 'male'

var person = new Sub()
alert(person.__proto__.__proto__ === Super.prototype); // true
alert(person.__proto__.__proto__.constructor === Super); // true

?
(2)默認(rèn)的原型
? 需要了解的是,所有的函數(shù)的默認(rèn)原型都是Object的實(shí)例簇搅,也就是說完域,所有的自定義構(gòu)造函數(shù)都默認(rèn)繼承了原生的Object類型,而這個繼承也是通過原型鏈實(shí)現(xiàn)的瘩将。因此默認(rèn)原型都會包含一個內(nèi)部指針指向Object.prototype吟税,這也是為什么所有的自定義類型都有toString()valueOf()等默認(rèn)的方法的根本原因姿现。
? 因此針對上述實(shí)踐肠仪,我們可以再加上默認(rèn)的原型,就有了如下關(guān)系

alert(person.__proto__.__proto__.__proto__ === Object.prototype) // true
alert(person.__proto__.__proto__.__proto__.constructor === Object) // true

# 確定實(shí)例和原型的關(guān)系

(1) instanceof

? instance 即:“實(shí)例”备典。instanceof操作符用來表示操作符左側(cè)的實(shí)例是否是右側(cè)構(gòu)造函數(shù)實(shí)例化來的异旧,這個構(gòu)造函數(shù)可以是實(shí)例原型鏈上constructor中的一員。借用上面的例子有:

person instanceof Sub // true
person instanceof Super  // true
person instanceof Object // true

? 在真實(shí)業(yè)務(wù)環(huán)境中提佣,通常判斷的是直接由原生構(gòu)造函數(shù)Object或Array創(chuàng)建的實(shí)例吮蛹,原型鏈上只有一環(huán),就是如上第三個表達(dá)式拌屏。
? 以對象為例來看instanceof 操作符的執(zhí)行原理潮针,其實(shí)就是操作符右側(cè)的構(gòu)造函數(shù)的原型指針,和操作符左側(cè)的原型指針是否指向了同一個原型對象倚喂。

person instanceof Object
每篷!等價于判斷
person.__proto__=== Object.prototype
!注意不是以下判斷务唐,可以用字面量發(fā)重定義原型再修改原型構(gòu)造函數(shù)的constructor來驗(yàn)證
person.__proto__.constructor===Object
(2) isPrototypeOf()

? isPrototypeOf()方法是原型對象的一個方法屬性雳攘,表示只要是原型鏈中出現(xiàn)過的原型,都是該原型鏈所派生的實(shí)例的原型枫笛《置穑或者理解為:某個構(gòu)造函數(shù)的原型對象,是否是某個實(shí)例的原型鏈上的一員刑巧。上面的例子用該方法描述即:

Object.prototype.isPrototypeOf(person)  // true
Super.prototype.isPrototypeOf(person)  // true
Sub.prototype.isPrototypeOf(person)  // true
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喧兄,一起剝皮案震驚了整個濱河市无畔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吠冤,老刑警劉巖浑彰,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拯辙,居然都是意外死亡郭变,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門涯保,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诉濒,“玉大人,你說我怎么就攤上這事夕春∥椿模” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵及志,是天一觀的道長片排。 經(jīng)常有香客問我,道長速侈,這世上最難降的妖魔是什么率寡? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮倚搬,結(jié)果婚禮上勇劣,老公的妹妹穿的比我還像新娘。我一直安慰自己潭枣,他們只是感情好比默,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盆犁,像睡著了一般命咐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谐岁,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天醋奠,我揣著相機(jī)與錄音,去河邊找鬼伊佃。 笑死窜司,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的航揉。 我是一名探鬼主播塞祈,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼帅涂!你這毒婦竟也來了议薪?” 一聲冷哼從身側(cè)響起尤蛮,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斯议,沒想到半個月后产捞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哼御,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年坯临,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恋昼。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡尿扯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焰雕,到底是詐尸還是另有隱情,我是刑警寧澤芳杏,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布矩屁,位于F島的核電站,受9級特大地震影響爵赵,放射性物質(zhì)發(fā)生泄漏吝秕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一空幻、第九天 我趴在偏房一處隱蔽的房頂上張望烁峭。 院中可真熱鬧,春花似錦秕铛、人聲如沸约郁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鬓梅。三九已至,卻和暖如春谨湘,著一層夾襖步出監(jiān)牢的瞬間绽快,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工紧阔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坊罢,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓擅耽,卻偏偏與公主長得像活孩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子乖仇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348