簡述JS面向?qū)ο缶幊?/h1>

大家好挂据,我是IT修真院深圳分院第01期學(xué)員娃弓,一枚正直純潔善良的web程序員雾狈。

今天給大家分享一下,修真院官網(wǎng)JS(職業(yè))任務(wù)4母怜,深度思考中的知識(shí)點(diǎn)——JS面向?qū)ο缶幊?/p>

1.介紹

“面向?qū)ο缶幊獭保∣bject-Oriented Programming余耽,縮寫為OOP)是目前主流的編程范式。它的核心思想是將真實(shí)世界中各種復(fù)雜的關(guān)系苹熏,抽象為一個(gè)個(gè)對(duì)象碟贾,然后由對(duì)象之間的分工與合作,完成對(duì)真實(shí)世界的模擬轨域。

面向?qū)ο蟮恼Z言有一個(gè)標(biāo)志袱耽,就是類的概念,通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象干发。ECMAScript中沒有類的概念扛邑,它的對(duì)象與基于類的語言中的對(duì)象有所不同。

2.涉及

2.1對(duì)象

ECMA-262 把對(duì)象定義為:無序?qū)傩缘募项砣唬鋵傩钥梢园局怠?duì)象或者函數(shù)恶座。嚴(yán)格來講搀暑,這就相當(dāng)于說對(duì)象是一組沒有特定順序的值。對(duì)象的每個(gè)屬性或方法都有一個(gè)名字跨琳,而每個(gè)名字都映射到一個(gè)值自点。正因?yàn)檫@樣(以及其他將要討論的原因).我們可以把 ECMAScript 的對(duì)象想象成散列表:無非就是一組名值對(duì),其中值可以是數(shù)據(jù)或函數(shù)脉让。

2.1.1Object構(gòu)造對(duì)象

var person = new Object();

person.name = "Nicholas";

person.age = 29;

person.job = "Software Engineer ";

person.sayName = function() {

alert (this.name) ;

};

2.1.2對(duì)象字面量創(chuàng)建對(duì)象

var person = {

name: "Nicholas",

age : 29 ,

job: "Software Engineer",

sayName: function () {

alert(this.name) ;

}

};

2.2對(duì)象屬性類型

ECMA-262第5版定義了JS對(duì)象屬性的特征(用于JS引擎桂敛,外部無法直接訪問)功炮。ECMAScript中有兩種屬性:數(shù)據(jù)屬性和訪問器屬性。

2.2.1數(shù)據(jù)屬性

數(shù)據(jù)屬性指包含一個(gè)數(shù)據(jù)值的位置术唬,可在該位置讀取或?qū)懭胫敌椒?個(gè)供述其行為的特性:

[[configurable]]:表示能否通過 delete 刪除屬性從而重新定義屬性.能否修改屬性的特性,或者能否把屬性修改為訪問器屬性粗仓。默認(rèn)為true;

[[Enumerable]]:表示能否通過 for-in 循環(huán)返回屬性嫁怀。默認(rèn)為true;

[[Writable]]:表示能否修改屬性的值。默認(rèn)true;

[[Value]]:包含該屬性的數(shù)據(jù)值借浊。讀取/寫入都是該值塘淑。默認(rèn)為undefined;

如上面實(shí)例對(duì)象person中定義了name屬性,其值為’Nicholas’,對(duì)該值的修改都反映在這個(gè)位置蚂斤,要修改對(duì)象屬性的默認(rèn)特征(默認(rèn)都為true)存捺,必須使用用Object.defineProperty()方法,它接收三個(gè)參數(shù):屬性所在對(duì)象曙蒸,屬性名和一個(gè)描述符對(duì)象(必須是:configurable捌治、enumberable、writable和value逸爵,可設(shè)置一個(gè)或多個(gè)值)具滴。

var person = {};

Object.defineProperty(person, 'name', {

configurable: false,

writable: false,

value: 'Nicholas'

});

alert(person.name);//"Nicholas"

delete person.name;

person.name = 'aaa';

alert(person.name);//"Nicholas"

以上,delete及重置person.name的值都沒有生效师倔,這就是因?yàn)閏onfigurable: false和writable: false构韵;值得注意的是一旦將configurable設(shè)置為false,則無法再使用defineProperty將其修改為true(執(zhí)行會(huì)報(bào)錯(cuò):can't redefine non-configurable property);

2.2.2訪問器屬性

訪問器屬性不包含數(shù)據(jù)值趋艘。它包含一對(duì) getter 和 setter 函數(shù)(這兩個(gè)函數(shù)都不是必需的)疲恢。讀取訪問器屬性時(shí),調(diào)用 getter 函數(shù)瓷胧,返回有效的值显拳;寫入訪問器屬性時(shí),調(diào)用 setter 函數(shù)并傳入新值并設(shè)置搓萧。該屬性有以下4個(gè)特征:

[[Configurable]]:是否可通過delete刪除屬性從而重新定義屬性杂数,能否修改屬性的特性,或者能否把屬性修改為數(shù)據(jù)屬性瘸洛,默認(rèn)值為true揍移。

[[Enumerable]]:是否可通過for-in循環(huán)屬性;

[[Get]]:讀取屬性時(shí)調(diào)用反肋,默認(rèn):undefined;

[[Set]]:寫入屬性時(shí)調(diào)用那伐,默認(rèn):undefined;

訪問器屬性不能直接定義,必須使用defineProperty()來定義.如:

var book = {

_year: 2004,

edition: 1

};

Object.defineProperty(book, 'year', {

get: function () {

return this._year;

},

set: function (newValue) {

if (newValue > 2004) {

this._year=newValue;

this.edition += newValue-2004;

}

}

});

book.year=2005;

alert(book.edition);//2

不一定非要同時(shí)指定 getter 和 setter,只指定 getter 意味著屬性是不能寫罕邀,嘗試寫入屬性會(huì)被忽略畅形。沒有指定getter函數(shù)的屬性也不能讀,會(huì)返回undefined。

此外诉探,ECMA-262(5)還提供了一個(gè)Object.defineProperties()方法日熬,可以用來一次性定義多個(gè)屬性的特性:

var book = {};

Object.defineProperties(book,{

_year:{

value:2004

},

edition:{

value:1

},

year:{

get: function () {

return this._year;

},

set: function (newValue) {

if (newValue > 2004) {

this._year=newValue;

this.edition += newValue-2004;

}}}

});

使用ECMAScript 5的Object.getOwnPropertyDescriptor()方法,可以取得給定屬性的描述符阵具。這個(gè)方法接收兩個(gè)參數(shù): 屬性所在的對(duì)象和要讀取其描述符的屬性名稱碍遍。返回值是一個(gè)對(duì)象,如果是訪問器屬性阳液,這個(gè)對(duì)象的屬性有configurable怕敬、enumerable、get和set; 如果是數(shù)據(jù)屬性帘皿,這個(gè)對(duì)象的屬性有configurable东跪、enumerable、writable和value鹰溜。

var descriptor = Object.getOwnPropertyDescriptor(book 虽填,"_year" ) ;

alert(descriptor.value); //2004

alert(descriptor.configurable); //false

alert(typeof descriptor.get); //undefined

var descriptor = Object.getOwnPropertyDescriptor(book. "year");

alert(descriptor.value); //undefined

alert(descriptor.enumerable); //false

alert(typeof descriptor.get); //function

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

使用Object構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢詣?chuàng)建對(duì)象,缺點(diǎn)是創(chuàng)建多個(gè)對(duì)象時(shí)曹动,會(huì)產(chǎn)生大量的重復(fù)代碼斋日。因此使用用工廠模式的變體來解決問題。

2.3.1工廠模式:用函數(shù)來封裝以特定接口創(chuàng)建對(duì)象的細(xì)節(jié)

function createPerson(name, age, job) {

var o = new Object();

o.name = name;

o.age = age;

o.job = job;

o.getName = function () {

return this.name;

}

return o;//使用return返回生成的對(duì)象實(shí)例

}

var person = createPerson('Nicholas',29,'Software Engineer');

var person = createPerson('Greg',27,'Doctor');

創(chuàng)建對(duì)象交給一個(gè)工廠方法來實(shí)現(xiàn)墓陈,可以傳遞參數(shù)恶守。缺點(diǎn)是無法識(shí)別對(duì)象類型,因?yàn)閯?chuàng)建對(duì)象都是使用Object的原生構(gòu)造函數(shù)來完成的贡必。

2.3.2構(gòu)造函數(shù)模式:創(chuàng)建特定類型的對(duì)象

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.getName = function () {

return this.name;

}

}

var person1 = new Person('Nicholas',29,'Software Engineer');

var person2 = new Person('Greg',27,'Doctor');

使用自定義的構(gòu)造函數(shù)來創(chuàng)建對(duì)象兔港,它與工廠方法區(qū)別在于:

1.沒有顯式地創(chuàng)建對(duì)象

2.直接將屬性和方法賦值給this對(duì)象;

3.沒有return語句仔拟;

此外衫樊,要?jiǎng)?chuàng)建Person的實(shí)例,必須使用new關(guān)鍵字利花,以Person函數(shù)為構(gòu)造函數(shù)科侈,傳遞參數(shù)完成對(duì)象創(chuàng)建;實(shí)際創(chuàng)建經(jīng)過以下4個(gè)過程:

1.創(chuàng)建一個(gè)對(duì)象

2.將函數(shù)的作用域賦給新對(duì)象(因此this指向這個(gè)新對(duì)象炒事,如:person1)

3.執(zhí)行構(gòu)造函數(shù)的代碼

4.返回該對(duì)象

上面person1與person2都是Person的實(shí)例兑徘,可以使用instanceof判斷,且都繼承了Object羡洛。

alert(person1 instanceof Person);//true;

alert(person2 instanceof Person);//true;

alert(person1 instanceof Object);//true;

alert(person1.constructor === person2.constructor);//ture;

構(gòu)造函數(shù)方式也存在缺點(diǎn),那就是在創(chuàng)建對(duì)象時(shí),特別針對(duì)對(duì)象的屬性指向函數(shù)時(shí)欲侮,會(huì)重復(fù)的創(chuàng)建函數(shù)實(shí)例崭闲,以上述代碼為基礎(chǔ),可以改寫為:

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = new Function ("alert(this.name)");//與聲明函數(shù)在邏輯上是等價(jià)的

}

alert(person1.sayName == person2.sayName); //false

上述代碼威蕉,創(chuàng)建多個(gè)實(shí)例時(shí)刁俭,會(huì)重復(fù)調(diào)用new Function(),創(chuàng)建多個(gè)函數(shù)實(shí)例韧涨,這些函數(shù)實(shí)例不在一個(gè)作用域中牍戚,造成內(nèi)存浪費(fèi)。

可以在函數(shù)中定義一個(gè)this.sayName = sayName的引用虑粥,而sayName函數(shù)在Person外定義如孝,這樣可以解決重復(fù)創(chuàng)建函數(shù)實(shí)例問題,但在效果上并沒有起到封裝的效果娩贷,如下所示:

function Person(name,age,job){

this.name = name;

this.age = age;

this.job = job;

this.sayName = sayName;

}

function sayName() {

alert(this.name);

}

var person1 = new Person('Nicholas',29,'Software Engineer');

var person2 = new Person('Greg',27,'Doctor');

2.3.3原型模式

JS每個(gè)函數(shù)都有一個(gè)prototype(原型)屬性第晰,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象彬祖,它是所有通過new操作符使用函數(shù)創(chuàng)建的實(shí)例的原型對(duì)象茁瘦。原型對(duì)象最大特點(diǎn)是,所有對(duì)象實(shí)例共享它所包含的屬性和方法储笑,也就是說甜熔,所有在原型對(duì)象中創(chuàng)建的屬性或方法都直接被所有對(duì)象實(shí)例共享。

function Person(){

}

Person.prototype.name = 'Nicholas'; //使用原型來添加屬性

Person.prototype.age = 29;

person.prototype.job = 'Software Engineer';

Person.prototype.sayName = function(){

alert(this.name);

}

var person1 = new Person();

person1.sayName(); //Nicholas

var person2 = new Person();

person2.sayName(); //Nicholas

alert(person1.sayName === person2.sayName); //true;

原型模式的缺點(diǎn)突倍,它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)腔稀,結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值。最主要是當(dāng)對(duì)象的屬性是引用類型時(shí)赘方,它的值是不變的烧颖,總是引用同一個(gè)外部對(duì)象,所有實(shí)例對(duì)該對(duì)象的操作都會(huì)影響其它實(shí)例:

function Person() {

}

Person.prototype ={

name:'Nicholas',

lessons = ['Math','Physics'];

}

var person1 = new Person();

var person2 = new Person();

person1.lessons.push('Biology');

alert(person2.lessons);//Math,Physics,Biology窄陡,修改person1影響了person2

2.3.4組合構(gòu)造函數(shù)及原型模式

目前最為常用的定義類型方式炕淮,是組合使用構(gòu)造函數(shù)模式與原型模式。構(gòu)造函數(shù)模式用于定義實(shí)例的屬性跳夭,而原型模式用于定義方法和共享的屬性涂圆。結(jié)果,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性的副本币叹,但同時(shí)又共享著對(duì)方方法的引用润歉,最大限度的節(jié)約內(nèi)存。

function Person(name,age,job) {

this.name = name;

this.age = age;

this.job = job;

this.friends = ['Shelby','Court'];

}

Person.prototype ={

constructor: Person,

this.sayName: function() {

alert(this.name);

}

}

var person1 = new Person('Nicholas',29,'Software Engineer');

var person2 = new Person('Greg',27,'Doctor');

person1.friends.push('Van');

alert(person1.friends); //"Shelby,Court,Van"

alert(person2.friends); //"Shelby,Court"

alert(parson1.friends === parson2.friends); //false

alert(parson1.sayName === parson2.sayName); //true

2.3.5動(dòng)態(tài)原型模式

將所有信息封裝在構(gòu)造函數(shù)中颈抚,而通過在構(gòu)造函數(shù)中初始化原型(僅在必要的情況下)踩衩,又保持了同時(shí)使用構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)。換句話說,可以通過檢查某個(gè)應(yīng)該存在的方法是否有效驱富,來決定是否需要初始化原型锚赤。

function Person(name,age,job) {

this.name = name;

this.age = age;

this.job = job;

//方法

if (typeof this.sayName != 'function'){

Person.prototype.sayName = function() {

alert(this.name);

};

}

}

var person1 = new Person('Nicholas',29,'Software Engineer');

person1.sayName();

方法代碼:if語句在sayName()方法不存在的情況下,將它添加到原型中褐鸥,只在初次調(diào)用構(gòu)造函數(shù)時(shí)執(zhí)行线脚。對(duì)于采用這種模式創(chuàng)建的對(duì)象,可以使用instanceof操作符確定它的類型叫榕。

2.4 繼承

ECMAScript 無法實(shí)現(xiàn)接口繼承浑侥,只支持實(shí)現(xiàn)繼承。

2.4.1原型鏈

上一期講過

2.4.2借用構(gòu)造函數(shù)

使用apply()和call()方法在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)晰绎。

function SuperType() {

this.colors = ['red', 'blue','green'];

}

function SubType() (

// 繼承了SuperType

SuperType.call(this);

}

var instance1 = new SubType() ;

instance1.colors.push("black");

alert (instance1.colors); / /"red,blue,green,black"

var instance2 = new SubType();

alert(instance2.colors); //"red,blue,green"

2.4.3組合繼承

使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承寓落,而通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。

function SuperType(name) {

this.name = name;

this.colors = ["red","blue","green"];

}

SuperType.prototype.sayName = function () (

alert(this.name);

};

function SubType(name,age) (

//繼承屬性

SuperType.call(this,name);

this.age = age;

}

/ /繼承方法

SubType.prototype = new SuperType();

SubType.prototype.constructor=SubType;

SubType.prototype.sayAge = function() (

alert(this.age);

};

var instance1 = new SubType('Nicholas',29);

instance1.colors.push('black');

alert(instance1.colors); // "red,blue,green,black"

instance1.sayName(); //'Nicholas';

instance1.sayAge(); //29

var instance2 = new SubType('Greg',27);

alert(instance2.colors); //'red, blue, green'

instance2.sayName(); //'Greg';

instance2.sayAge(); //27

讓兩個(gè)不同的 SubType 實(shí)例既分別擁有自己屬性————包括colors屬性寒匙,又可以使用相同的方法零如。

此外,還存在下列可供選擇的繼承模式锄弱。

1).原型式繼承. 可以在不必預(yù)先定義構(gòu)造函數(shù)的情況下實(shí)現(xiàn)繼承考蕾,其本質(zhì)是執(zhí)行對(duì)給定對(duì)象的淺復(fù)制。而復(fù)制得到的副本還可以得到進(jìn)一步改造会宪。

2).寄生式繼承. 與原型式繼承非常相似.也是基于某個(gè)對(duì)象或某些信息創(chuàng)建一個(gè)對(duì)象肖卧,然后增強(qiáng)對(duì)象,最后返回對(duì)象掸鹅。為了解決組合繼承模式由于多次調(diào)用超類型構(gòu)造函數(shù)而導(dǎo)致的低效率問題塞帐,可以將這個(gè)模式與組合繼承一起使用。

3).寄生組合式繼承. 集寄生式繼承和組合繼承的優(yōu)點(diǎn)與一身巍沙,是實(shí)現(xiàn)基于類型繼承的最有效方式葵姥。

3.常見問題

面向?qū)ο缶幊?br>

4.解決方案

以上

5.編碼實(shí)戰(zhàn)

6.擴(kuò)展思考

面向?qū)ο笈c面向過程的區(qū)別?

傳統(tǒng)的過程式編程(procedural programming)由一系列函數(shù)或一系列指令組成句携,使用時(shí)一步步調(diào)用榔幸;而面向?qū)ο缶幊痰某绦蛴梢幌盗袑?duì)象組成。

每一個(gè)對(duì)象都是功能中心矮嫉,具有明確分工削咆,可以完成接受信息、處理數(shù)據(jù)蠢笋、發(fā)出信息等任務(wù)拨齐。因此,面向?qū)ο缶幊叹哂徐`活性昨寞、代碼的可重用性瞻惋、模塊性等特點(diǎn)厦滤,容易維護(hù)和開發(fā),非常適合多人合作的大型應(yīng)用型軟件項(xiàng)目熟史。

7.參考文獻(xiàn)

《Javascript高級(jí)程序設(shè)計(jì)》chapter 6

8.更多討論

狀態(tài)機(jī)也是用對(duì)象實(shí)現(xiàn)的馁害。

鳴謝

PPT鏈接

感謝大家觀看


簡述JS面向?qū)ο缶幊蘝騰訊視頻

------------------------------------------------------------------------------------------------------------------------

今天的分享就到這里啦,歡迎大家點(diǎn)贊蹂匹、轉(zhuǎn)發(fā)、留言凹蜈、拍磚~

下期預(yù)告:cookies限寞,sessionStorage和localStorage的區(qū)別?不見不散~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末仰坦,一起剝皮案震驚了整個(gè)濱河市履植,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悄晃,老刑警劉巖玫霎,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妈橄,居然都是意外死亡庶近,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門眷蚓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鼻种,“玉大人,你說我怎么就攤上這事沙热〔嬖浚” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵篙贸,是天一觀的道長投队。 經(jīng)常有香客問我,道長爵川,這世上最難降的妖魔是什么敷鸦? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮雁芙,結(jié)果婚禮上轧膘,老公的妹妹穿的比我還像新娘。我一直安慰自己兔甘,他們只是感情好谎碍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洞焙,像睡著了一般蟆淀。 火紅的嫁衣襯著肌膚如雪拯啦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天熔任,我揣著相機(jī)與錄音褒链,去河邊找鬼。 笑死疑苔,一個(gè)胖子當(dāng)著我的面吹牛甫匹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惦费,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼兵迅,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了薪贫?” 一聲冷哼從身側(cè)響起恍箭,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞧省,沒想到半個(gè)月后扯夭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞍匾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年交洗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片候学。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡藕筋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梳码,到底是詐尸還是另有隱情隐圾,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布掰茶,位于F島的核電站暇藏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏濒蒋。R本人自食惡果不足惜盐碱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沪伙。 院中可真熱鬧瓮顽,春花似錦、人聲如沸围橡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翁授。三九已至拣播,卻和暖如春晾咪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贮配。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工谍倦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泪勒。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓昼蛀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親圆存。 傳聞我的和親對(duì)象是個(gè)殘疾皇子曹洽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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