原型對(duì)象

理解原型對(duì)象

無論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象影涉。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor(構(gòu)造函數(shù))屬性规伐,這個(gè)屬性包含一個(gè)指向prototype 屬性所在函數(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();

就拿前面的例子來說,Person.prototype. constructor 指向Person猖闪。而通過這個(gè)構(gòu)造函數(shù)鲜棠,我們還可繼續(xù)為原型對(duì)象添加其他屬性和方法。

更簡單的原型語法

前面例子中每添加一個(gè)屬性和方法就要敲一遍Person.prototype培慌。為減少不必要的輸入豁陆,也為了從視覺上更好地封裝原型的功能,更常見的做法是用一個(gè)包含所有屬性和方法的對(duì)象字面量來重寫整個(gè)原型對(duì)象吵护,如下面的例子所示盒音。

function Person() {}
Person.prototype = {
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};

在上面的代碼中表鳍,我們將Person.prototype 設(shè)置為等于一個(gè)以對(duì)象字面量形式創(chuàng)建的新對(duì)象。

最終結(jié)果相同祥诽,但有一個(gè)例外:constructor 屬性不再指向Person 了譬圣。前面曾經(jīng)介紹過,每創(chuàng)建一個(gè)函數(shù)雄坪,就會(huì)同時(shí)創(chuàng)建它的prototype 對(duì)象厘熟,這個(gè)對(duì)象也會(huì)自動(dòng)獲得constructor 屬性。而我們在這里使用的語法维哈,本質(zhì)上完全重寫了默認(rèn)的prototype 對(duì)象绳姨,因此constructor 屬性也就變成了新對(duì)象的constructor 屬性(指向Object 構(gòu)造函數(shù)),不再指向Person 函數(shù)阔挠。此時(shí)飘庄,盡管instanceof操作符還能返回正確的結(jié)果,但通過constructor 已經(jīng)無法確定對(duì)象的類型了购撼,如下所示竭宰。

var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true

在此,用instanceof 操作符測試Object 和Person 仍然返回true份招,但constructor 屬性則等于Object 而不等于Person 了。如果constructor 的值真的很重要狞甚,可以像下面這樣特意將它設(shè)置回適當(dāng)?shù)闹怠?/p>

function Person() {}
Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};

以上代碼特意包含了一個(gè)constructor 屬性锁摔,并將它的值設(shè)置為Person,從而確保了通過該屬性能夠訪問到適當(dāng)?shù)闹怠?/p>

注意:
以這種方式重設(shè)constructor 屬性會(huì)導(dǎo)致它的[[Enumerable]]特性被設(shè)置為true哼审。默認(rèn)情況下谐腰,原生的constructor 屬性是不可枚舉的(枚舉:就是遍歷對(duì)象的時(shí)候,此屬性可以和普通屬性一樣涩盾,被直接獲取十气。),因此如果你使用兼容ECMAScript 5 的JavaScript 引擎春霍,可以試一試Object.defineProperty()砸西。

function Person() {}
Person.prototype = {
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};
 
//重設(shè)構(gòu)造函數(shù),只適用于ECMAScript 5 兼容的瀏覽器
Object.defineProperty(Person.prototype, "constructor", {
    enumerable: false,
    value: Person
});

原型的動(dòng)態(tài)性

由于在原型中查找值的過程是一次搜索址儒,因此我們對(duì)原型對(duì)象所做的任何修改都能夠立即從實(shí)例上反映出來——即使是先創(chuàng)建了實(shí)例后修改原型也照樣如此芹枷。請看下面的例子。

var friend = new Person();
Person.prototype.sayHi = function(){
    alert("hi");
};
friend.sayHi(); //"hi"(沒有問題Aぁ)

以上代碼先創(chuàng)建了Person 的一個(gè)實(shí)例鸳慈,并將其保存在person 中。然后喧伞,下一條語句在Person.prototype 中添加了一個(gè)方法sayHi()走芋。即使person 實(shí)例是在添加新方法之前創(chuàng)建的绩郎,但它仍然可以訪問這個(gè)新方法。其原因可以歸結(jié)為實(shí)例與原型之間的松散連接關(guān)系翁逞。當(dāng)我們調(diào)用person.sayHi()時(shí)肋杖,首先會(huì)在實(shí)例中搜索名為sayHi 的屬性,在沒找到的情況下熄攘,會(huì)繼續(xù)搜索原型兽愤。因?yàn)閷?shí)例與原型之間的連接只不過是一個(gè)指針,而非一個(gè)副本挪圾,因此就可以在原型中找到新的sayHi 屬性并返回保存在那里的函數(shù)浅萧。

盡管可以隨時(shí)為原型添加屬性和方法,并且修改能夠立即在所有對(duì)象實(shí)例中反映出來哲思,但如果是重寫整個(gè)原型對(duì)象洼畅,那么情況就不一樣了。我們知道棚赔,調(diào)用構(gòu)造函數(shù)時(shí)會(huì)為實(shí)例添加一個(gè)指向最初原型的[[Prototype]]指針帝簇,而把原型修改為另外一個(gè)對(duì)象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。請記卓恳妗:實(shí)例中的指針僅指向原型丧肴,而不指向構(gòu)造函數(shù)‰屎螅看下面的例子芋浮。

function Person() {}
var friend = new Person();
Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};
friend.sayName(); //error

在這個(gè)例子中,我們先創(chuàng)建了Person 的一個(gè)實(shí)例壳快,然后又重寫了其原型對(duì)象纸巷。然后在調(diào)用friend.sayName()時(shí)發(fā)生了錯(cuò)誤,因?yàn)閒riend 指向的原型中不包含以該名字命名的屬性眶痰。


image.png

原型對(duì)象的問題

原型模式也不是沒有缺點(diǎn)瘤旨。首先,它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié)竖伯,結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值存哲。雖然這會(huì)在某種程度上帶來一些不方便,但還不是原型的最大問題黔夭。

原型模式的最大問題是由其共享的本性所導(dǎo)致的宏胯。

原型中所有屬性是被很多實(shí)例共享的,這種共享對(duì)于函數(shù)非常合適本姥。對(duì)于那些包含基本值的屬性倒也說得過去肩袍,畢竟(如前面的例子所示),通過在實(shí)例上添加一個(gè)同名屬性婚惫,可以隱藏原型中的對(duì)應(yīng)屬性氛赐。然而魂爪,對(duì)于包含引用類型值的屬性來說,問題就比較突出了艰管。來看下面的例子滓侍。

function Person() {}
Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    friends: ["Shelby", "Court"],
    sayName: function() {
        alert(this.name);
    }
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true

在此,Person.prototype 對(duì)象有一個(gè)名為friends 的屬性牲芋,該屬性包含一個(gè)字符串?dāng)?shù)組撩笆。然后,創(chuàng)建了Person 的兩個(gè)實(shí)例缸浦。接著夕冲,修改了person1.friends 引用的數(shù)組,向數(shù)組中添加了一個(gè)字符串裂逐。由于friends 數(shù)組存在于Person.prototype 而非person1 中歹鱼,所以剛剛提到的修改也會(huì)通過person2.friends(與person1.friends 指向同一個(gè)數(shù)組)反映出來。假如我們的初衷就是像這樣在所有實(shí)例中共享一個(gè)數(shù)組卜高,那么對(duì)這個(gè)結(jié)果我沒有話可說弥姻。可是掺涛,實(shí)例一般都是要有屬于自己的全部屬性的庭敦。而這個(gè)問題正是我們很少看到有人單獨(dú)使用原型模式的原因所在。

組合使用構(gòu)造函數(shù)模式和原型模式

創(chuàng)建自定義類型的最常見方式薪缆,就是組合使用構(gòu)造函數(shù)模式與原型模式螺捐。構(gòu)造函數(shù)模式用于定義實(shí)例屬性,而原型模式用于定義方法和共享的屬性矮燎。結(jié)果,每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性的副本赔癌,但同時(shí)又共享著對(duì)方法的引用诞外,最大限度地節(jié)省了內(nèi)存。另外灾票,這種混成模式還支持向構(gòu)造函數(shù)傳遞參數(shù)峡谊;可謂是集兩種模式之長。下面的代碼重寫了前面的例子刊苍。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];
}
Person.prototype = {
    constructor: Person,
    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,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

在這個(gè)例子中既们,實(shí)例屬性都是在構(gòu)造函數(shù)中定義的,而由所有實(shí)例共享的屬性constructor 和方法sayName()則是在原型中定義的正什。而修改了person1.friends(向其中添加一個(gè)新字符串)啥纸,并不會(huì)影響到person2.friends,因?yàn)樗鼈兎謩e引用了不同的數(shù)組婴氮。

這種構(gòu)造函數(shù)與原型混成的模式斯棒,是目前在ECMAScript 中使用最廣泛盾致、認(rèn)同度最高的一種創(chuàng)建自定義類型的方法∪倌海可以說庭惜,這是用來定義引用類型的一種默認(rèn)模式。

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

有其他OO 語言經(jīng)驗(yàn)的開發(fā)人員在看到獨(dú)立的構(gòu)造函數(shù)和原型時(shí)穗酥,很可能會(huì)感到非常困惑护赊。動(dòng)態(tài)原型模式正是致力于解決這個(gè)問題的一個(gè)方案,它把所有信息都封裝在了構(gòu)造函數(shù)中砾跃,而通過在構(gòu)造函數(shù)中初始化原型(僅在必要的情況下)骏啰,又保持了同時(shí)使用構(gòu)造函數(shù)和原型的優(yōu)點(diǎn)。換句話說蜓席,可以通過檢查某個(gè)應(yīng)該存在的方法是否有效器一,來決定是否需要初始化原型。來看一個(gè)例子厨内。

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 friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName();

注意構(gòu)造函數(shù)代碼中加粗的部分祈秕。這里只在sayName()方法不存在的情況下,才會(huì)將它添加到原型中雏胃。這段代碼只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)執(zhí)行请毛。此后,原型已經(jīng)完成初始化瞭亮,不需要再做什么修改了方仿。不過要記住,這里對(duì)原型所做的修改统翩,能夠立即在所有實(shí)例中得到反映仙蚜。因此,這種方法確實(shí)可以說非常完美厂汗。其中委粉,if 語句檢查的可以是初始化之后應(yīng)該存在的任何屬性或方法——不必用一大堆if 語句檢查每個(gè)屬性和每個(gè)方法;只要檢查其中一個(gè)即可娶桦。對(duì)于采用這種模式創(chuàng)建的對(duì)象贾节,還可以使用instanceof 操作符確定它的類型。

使用動(dòng)態(tài)原型模式時(shí)衷畦,不能使用對(duì)象字面量重寫原型栗涂。前面已經(jīng)解釋過了,如果在已經(jīng)創(chuàng)建了實(shí)例的情況下重寫原型祈争,那么就會(huì)切斷現(xiàn)有實(shí)例與新原型之間的聯(lián)系

寄生構(gòu)造函數(shù)模式

通常斤程,在前述的幾種模式都不適用的情況下,可以使用寄生(parasitic)構(gòu)造函數(shù)模式菩混。這種模式的基本思想是創(chuàng)建一個(gè)函數(shù)暖释,該函數(shù)的作用僅僅是封裝創(chuàng)建對(duì)象的代碼袭厂,然后再返回新創(chuàng)建的對(duì)象;但從表面上看球匕,這個(gè)函數(shù)又很像是典型的構(gòu)造函數(shù)纹磺。下面是一個(gè)例子。

function Person(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    };
    return o;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

在這個(gè)例子中亮曹,Person 函數(shù)創(chuàng)建了一個(gè)新對(duì)象橄杨,并以相應(yīng)的屬性和方法初始化該對(duì)象,然后又返回了這個(gè)對(duì)象照卦。除了使用new 操作符并把使用的包裝函數(shù)叫做構(gòu)造函數(shù)之外式矫,這個(gè)模式跟工廠模式其實(shí)是一模一樣的。構(gòu)造函數(shù)在不返回值的情況下役耕,默認(rèn)會(huì)返回新對(duì)象實(shí)例采转。而通過在構(gòu)造函數(shù)的末尾添加一個(gè)return 語句,可以重寫調(diào)用構(gòu)造函數(shù)時(shí)返回的值瞬痘。

這個(gè)模式可以在特殊的情況下用來為對(duì)象創(chuàng)建構(gòu)造函數(shù)故慈。假設(shè)我們想創(chuàng)建一個(gè)具有額外方法的特殊數(shù)組。由于不能直接修改Array 構(gòu)造函數(shù)框全,因此可以使用這個(gè)模式察绷。

function SpecialArray() {
    //創(chuàng)建數(shù)組
    var values = new Array();
    //添加值
    values.push.apply(values, arguments);
    //添加方法
    values.toPipedString = function() {
        return this.join("|");
    };
    //返回?cái)?shù)組
    return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"

在這個(gè)例子中,我們創(chuàng)建了一個(gè)名叫SpecialArray 的構(gòu)造函數(shù)津辩。在這個(gè)函數(shù)內(nèi)部拆撼,首先創(chuàng)建了一個(gè)數(shù)組,然后push()方法(用構(gòu)造函數(shù)接收到的所有參數(shù))初始化了數(shù)組的值喘沿。隨后闸度,又給數(shù)組實(shí)例添加了一個(gè)toPipedString()方法,該方法返回以豎線分割的數(shù)組值蚜印。最后筋岛,將數(shù)組以函數(shù)值的形式返回。接著晒哄,我們調(diào)用了SpecialArray 構(gòu)造函數(shù),向其中傳入了用于初始化數(shù)組的值肪获,此后又調(diào)用了toPipedString()方法寝凌。

關(guān)于寄生構(gòu)造函數(shù)模式,有一點(diǎn)需要說明:首先孝赫,返回的對(duì)象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性之間沒有關(guān)系较木;也就是說,構(gòu)造函數(shù)返回的對(duì)象與在構(gòu)造函數(shù)外部創(chuàng)建的對(duì)象沒有什么不同青柄。為此伐债,不能依賴instanceof 操作符來確定對(duì)象類型预侯。由于存在上述問題,我們建議在可以使用其他模式的情況下峰锁,不要使用這種模式萎馅。

穩(wěn)妥構(gòu)造函數(shù)模式

道格拉斯·克羅克福德(Douglas Crockford)發(fā)明了JavaScript 中的穩(wěn)妥對(duì)象(durable objects)這個(gè)概念。所謂穩(wěn)妥對(duì)象虹蒋,指的是沒有公共屬性糜芳,而且其方法也不引用this 的對(duì)象。穩(wěn)妥對(duì)象最適合在一些安全的環(huán)境中(這些環(huán)境中會(huì)禁止使用this 和new)魄衅,或者在防止數(shù)據(jù)被其他應(yīng)用程序(如Mashup程序)改動(dòng)時(shí)使用峭竣。穩(wěn)妥構(gòu)造函數(shù)遵循與寄生構(gòu)造函數(shù)類似的模式,但有兩點(diǎn)不同:一是新創(chuàng)建對(duì)象的實(shí)例方法不引用this晃虫;二是不使用new 操作符調(diào)用構(gòu)造函數(shù)皆撩。按照穩(wěn)妥構(gòu)造函數(shù)的要求,可以將前面的Person 構(gòu)造函數(shù)重寫如下哲银。

function Person(name, age, job) {
    //創(chuàng)建要返回的對(duì)象
    var o = new Object();
    //可以在這里定義私有變量和函數(shù)
    //添加方法
    o.sayName = function() {
        alert(name);
    };
    //返回對(duì)象
    return o;
}

注意:
在以這種模式創(chuàng)建的對(duì)象中扛吞,除了使用sayName()方法之外,沒有其他辦法訪問name 的值盘榨。

可以像下面使用穩(wěn)妥的Person 構(gòu)造函數(shù)喻粹。

var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

這樣,變量friend 中保存的是一個(gè)穩(wěn)妥對(duì)象草巡,而除了調(diào)用sayName()方法外守呜,沒有別的方式可以訪問其數(shù)據(jù)成員。即使有其他代碼會(huì)給這個(gè)對(duì)象添加方法或數(shù)據(jù)成員山憨,但也不可能有別的辦法訪問傳入到構(gòu)造函數(shù)中的原始數(shù)據(jù)查乒。穩(wěn)妥構(gòu)造函數(shù)模式提供的這種安全性,使得它非常適合在某些安全執(zhí)行環(huán)境——例如郁竟,ADsafe(www.adsafe.org)和Caja(http://code.google.com/p/google-caja/)提供的環(huán)境——下使用玛迄。

與寄生構(gòu)造函數(shù)模式類似,使用穩(wěn)妥構(gòu)造函數(shù)模式創(chuàng)建的對(duì)象與構(gòu)造函數(shù)之間也沒有什么關(guān)系棚亩,因此instanceof 操作符對(duì)這種對(duì)象也沒有意義蓖议。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市讥蟆,隨后出現(xiàn)的幾起案子勒虾,更是在濱河造成了極大的恐慌,老刑警劉巖瘸彤,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件修然,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)愕宋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門玻靡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人中贝,你說我怎么就攤上這事囤捻。” “怎么了雄妥?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵最蕾,是天一觀的道長。 經(jīng)常有香客問我老厌,道長瘟则,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任枝秤,我火速辦了婚禮醋拧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淀弹。我一直安慰自己丹壕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布薇溃。 她就那樣靜靜地躺著菌赖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沐序。 梳的紋絲不亂的頭發(fā)上琉用,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音策幼,去河邊找鬼邑时。 笑死,一個(gè)胖子當(dāng)著我的面吹牛特姐,可吹牛的內(nèi)容都是我干的晶丘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼唐含,長吁一口氣:“原來是場噩夢啊……” “哼浅浮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捷枯,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤滚秩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后铜靶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年争剿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了已艰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蚕苇,死狀恐怖哩掺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涩笤,我是刑警寧澤嚼吞,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蹬碧,受9級(jí)特大地震影響舱禽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恩沽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一誊稚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罗心,春花似錦里伯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至飒箭,卻和暖如春狼电,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背补憾。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工漫萄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盈匾。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓腾务,卻偏偏與公主長得像,于是被迫代替她去往敵國和親削饵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岩瘦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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