摘要:在構(gòu)造函數(shù)內(nèi)部,將屬性設(shè)置成等于全局的函數(shù)。調(diào)用構(gòu)造函數(shù)的一個實例后,該實例內(nèi)部將包含一個指針中稱為,指向構(gòu)造函數(shù)的原型對象。原型對象的問題省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實例在默認情況下都取得相同的屬性值。
創(chuàng)建對象
使用對象字面量的形式一個接口會創(chuàng)建很多對象, 會產(chǎn)生大量的重復(fù)代碼。
工廠模式:用函數(shù)來封裝以特定接口創(chuàng)建對象的細節(jié)function createPerson (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 person1 = createPerson("Simon", 29, "software Engineer"); var person2 = createPerson("Zaynex",22, "Doctor");
這種模式解決了創(chuàng)建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)
構(gòu)造函數(shù)模式- 可用于創(chuàng)建特定模式的對象,像Object、Array等原生構(gòu)造函數(shù),在運行時會自動出現(xiàn)在執(zhí)行環(huán)境中。
我們利用構(gòu)造函數(shù)重寫下剛才的函數(shù)。
function createPerson(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); }; } var person1 = new Person("Simon",29, "software Engineer"); var person2 = new Person("Simon",29, "software Engineer");構(gòu)造函數(shù)與工廠模式的差異
沒有顯示地創(chuàng)建對象;
直接將屬性和方法賦給this對象;
沒有 return 語句;
我們注意到Person開頭是大寫,按照慣例來講,構(gòu)造函數(shù)開頭字母是大寫,非構(gòu)造函數(shù)以小寫字母開頭。
調(diào)用構(gòu)造函數(shù)四步驟創(chuàng)建一個新對象;
將構(gòu)造函數(shù)的作用域賦給新對象(因此this就指向了這個新對象);
執(zhí)行構(gòu)造函數(shù)中的代碼(為構(gòu)造函數(shù)新對象添加屬性)
返回新對象
person1和person2都保存著Person的一個不同的實例。這兩個對象都有一個constructor(構(gòu)造函數(shù))屬性,該屬性指向Person。
alert(person1.constructor == Person) //true; alert(person2.constructor == Person) //true;
對象的constructor屬性最初是用來標(biāo)識對象類型的。但是提到檢測對象類型,還是instanceof操作符更可靠一些。
alert(person1 instanceof Object); alert(person1 instanceof Person); alert(person2 instanceof Object); alert(person2 instanceof Person); //都為true.
我們所創(chuàng)建的所有對象都是Object的實例,同時也是Person的實例。
創(chuàng)建自定義的構(gòu)造函數(shù)意味著將來可以作為實例標(biāo)識為一種特定的類型;構(gòu)造函數(shù)模式勝過工廠模式的地方
把構(gòu)造函數(shù)當(dāng)函數(shù)- 任何函數(shù),只要通過 new 操作符來調(diào)用,那它就可以作為構(gòu)造函數(shù);
//當(dāng)做構(gòu)造函數(shù)使用
var person = new Person("Simon", 29, "software Engineer"); person.sayName(); //Simon //普通函數(shù)調(diào)用 Person("Genf", 23, "DOCTOR"); //添加到window window.sayName(); // Genf 以剛才的那種方式定義的構(gòu)造函數(shù)定義在Global對象中(在瀏覽器中是window對象),在全局作用域中調(diào)用函數(shù)時,this指向的是window對象 // 在另外一個對象的作用域中調(diào)用 var o = new Object(); Person.call(o, "Kristen", 25, "nusd"); o.sayName(); // Kristen構(gòu)造函數(shù)的缺陷
每個方法都要在每個實例上重新創(chuàng)建一遍。
person1 和 person2 都有一個名為 sayName() 的方法;但那兩個方法都不是同一個 Function 的實例,因此會有不同的作用域鏈和標(biāo)識符解析;不同實例上的同名函數(shù)是不同的。
不要忘了,每個函數(shù)都是一個對象!所以sayName方法也可以這樣寫,因此每個Person實例都包含著不同的Function實例。以這種方式創(chuàng)建函數(shù),會導(dǎo)致不同餓作用域和標(biāo)識符解析。
this.sayName = new Function("alert(this.name)"); //與聲明函數(shù)在邏輯上是等價的
我們可以檢驗下
alert(person1.sayName() == person2.sayName) //false;
創(chuàng)建兩個完成相同任務(wù)的Function 實例沒有必要,況且有this對象在,根本不用在執(zhí)行代碼前就把函數(shù)綁定到特定對象上面。
我們可以通過函數(shù)定義轉(zhuǎn)移構(gòu)造函數(shù)外部來解決這個問題。
function Person(name, age ,job)
{ this.name = name; this.age = age; this.sayName = sayName; } function sayName() { alert(this.name); } var person1 = new Person("Simon", 29, "software Engineer"); var person2 = new Person("Zaynex", 29, "DOCTOR");
把sayName()函數(shù)的定義轉(zhuǎn)移到了構(gòu)造函數(shù)外部。
在構(gòu)造函數(shù)內(nèi)部,將sayName屬性設(shè)置成等于全局的 sayName 函數(shù)。這樣sayName 包含的是一個指向函數(shù)的指針。 person1和person2共享同一個sayName()函數(shù)。
但問題是:
在全局作用域中定義的函數(shù)實際上只能被某個對象調(diào)用,如果對象需要定義很多方法,那么就要定義多個全局函數(shù)。
因此我們需要用原型模式來解決這個問題。
原型模式我們創(chuàng)建的每個函數(shù)都有一個 prototype(原型) 屬性,這個屬性屬于指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例的共享的屬性和方法。即通過構(gòu)造函數(shù)而創(chuàng)建的那個對象實例的原型對象。
我們不必將構(gòu)造函數(shù)定義對象實例的信息中,而是可以將這些信息直接添加到對象原型中。
function Person(){ } Person.prototype.name ="Simon"; Person.prototype.age = 29; Person.prototype.job = "software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); var person2 = new Person(); person2.sayName(); alert(person1.sayName == person2.sayName);
實際上,person1和person2都不包含屬性和方法, 但可以調(diào)用person1.sayName().這是通過查找對象屬性的過程來實現(xiàn)的。
理解原型對象無論何時,只要創(chuàng)建了新函數(shù),就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個 prototype 屬性,這個屬性指向函數(shù)的原型對象。
在默認情況下,所有原型都會自動獲得一個constructor(構(gòu)造函數(shù))屬性,這個屬性包含在一個指向 prototype屬性所在的函數(shù)的指針。舉例說明: Person.prototype.constructor 指向Person.
創(chuàng)建了自定義構(gòu)造函數(shù)之后,其原型對象默認只會取得 constructor 屬性。其他方法都是從Object繼承來的。
調(diào)用構(gòu)造函數(shù)的一個實例后,該實例內(nèi)部將包含一個指針(ES5中稱為[[Prototype]],指向構(gòu)造函數(shù)的原型對象。在腳本中沒有標(biāo)準形式訪問[[Prototype]],但在FF,SF,Chrome中的每個對象都支持屬性_proto_;在其他實現(xiàn)中,該屬性對腳本不可見。
要明確的是, 這個鏈接存在于實例與構(gòu)造函數(shù)的原型對象之間,而非實例與構(gòu)造函數(shù)之間。
雖然在現(xiàn)實中無法訪問到[[Prototype]],但可以通過 isPrototypeOf()來確定是否存在這種關(guān)系。
在ES5中新增一個方法,使用 Object.getPrototypeOf()可以方便的獲取一個對象的原型
每當(dāng)代碼讀取某個對象的某個屬性時,都會執(zhí)行一次搜索, 1.先從實例本身開始搜索屬性,存在,搜索結(jié)束。若不存在,執(zhí)行2 2.從實例的原型開始搜索屬性。
繼續(xù)剛才的代碼。如果我們繼續(xù)給實例添加相同的屬性,會怎樣?
function Person(){ } Person.prototype.name ="Simon"; Person.prototype.age = 29; Person.prototype.job = "software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = "xiwenzheng"; alert(person1.name) //xiwenzheng ——來自實例 alert(person2.name) // Simon ——來自原型
在person1這個實例中重寫屬性,那么解釋器搜索到了實例本身的屬性直接返回,對于person2而言,實例中沒有屬性,那么再往實例的原型開始搜素屬性。
給對象添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性,就是阻止我們訪問原型對象,但并不會修改原型對象中的同名屬性。即使將person1.name 設(shè)置為 null 也不會影響原型對象中的同步屬性。
不過delete 實例屬性,就可以訪問原型對象中的屬性了。
function Person(){
} Person.prototype.name ="Simon"; Person.prototype.age = 29; Person.prototype.job = "software Engineer"; Person.prototype.sayName = function(){ alert(this.name); };
var person1 = new Person(); var person2 = new Person(); person1.name = "xiwenzheng"; alert(person1.name); //xiwenzheng ——來自實例 alert(person2.name); // Simon ——來自原型 delete person1.name; alert(person1.name); // Simon 來自原型
使用hasOwnProperty()可以檢測一個屬性是否存在實例中還是存在原型中,這個方法只在給定屬性存在于對象實例中才會返回 true;
我們繼續(xù)采用剛才刪除部分的整段代碼。
alert(person1.hasOwnProperty("name")); // 返回false
原先person1.name是存在對象實例中的(被我們設(shè)為了"Zaynex"),但是被我們delete了。
如果我們不delete的話,那就是true了。要想獲得原型屬性的描述符,必須要在原型對象上調(diào)用 Object.hasOwnPropertydDsecriptor();
in 操作符會在通過對象能夠訪問給定屬性時返回 true ,不論該實行存在于實例中還是原型中。
利用in:判斷是否有該屬性
利用hasOwnProperty()判斷是否存在對象實例中;
結(jié)合以后就可以判斷該屬性是在原型中還是在實例中。
function hasPrototypeProperty(object, name ){
return !object.hasOwnProperty(name) && (name in object);
}
person1.name = "Zaynex";
alert(hasPrototypeProperty(person1, "name")); //false;存在實例中
for-in 循環(huán)時,返回的都是通過對象訪問的、可枚舉的屬性(即將[[Enumberable]]標(biāo)記為true的屬性),在ES5中constructor 和 prototype屬性的 [[Enumberable]]
設(shè)為false,但并不是所有瀏覽器都照此實現(xiàn)。
想取得對象上所有可枚舉的實例屬性,可以使用Object.Keys()方法。
function Person(){ } Person.prototype.name ="Simon"; Person.prototype.age = 29; Person.prototype.job = "software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var keys = Object.keys(Person.prototype); alert(keys);// name ,age, job, sayName var p1 = new Person(); p1.name = "Rob"; p1.age = 29; var p1keys = Object.keys(p1); alert(p1keys); // name ,age
如果想得到所有實例屬性,不論是否可枚舉,都可以使用 Object.getOwnPropertyNames()
var keys = Object.keys(Person.prototype); alert(keys);// constructor, name ,age, job, sayName更簡單的原型語法
之前的例子中每添加一個屬性和方法都要 Person.prototype,我們進行適當(dāng)?shù)姆庋b。
function Person(){ } Person.prototype = { name : "Simon", age : 29; job : "software Engineer", sayName : function () { alert(this.name); } };
我們將 Person.prototype 設(shè)置為等于一個以對象字面量形式創(chuàng)建的新對象。
之前介紹到,每創(chuàng)建一個函數(shù),同時會創(chuàng)建它的prototype對象,這個對象會指定獲得constructor 屬性。而我們在這里的語法本質(zhì)上是重寫了默認的 prototype 對象。
所以 constructor屬性也編程了新對象的屬性。(指向Object構(gòu)造函數(shù)),不再指向Person了。
instanceof 測試 Object 和 Person 都返回 true,但constructor 屬性則等于Object而不等于 Person ;
如果 constructor 的值很重要,則可以特意設(shè)置回適當(dāng)?shù)闹?/p>
function Person(){ } Person.prototype = { constructor:Person, name : "Simon", job : "software Engineer", sayName : function () { alert(this.name); } }
注意,以這種方式重設(shè)constructor屬性會導(dǎo)致 [[Enumberable]]特性設(shè)置為true,但默認我們是不可枚舉constructor屬性的。
為了兼容ES5的JS引擎,可以用 Object.defineProperty();
function Person(){ } Person.prototype = { name : "Simon", job : "software Engineer", sayName : function () { alert(this.name); } } Object.defineProperty(Person.prototype, "constructor", { enumerable: false, value: Person });原型的動態(tài)性
在原型中找值的過程是一次搜索,因此我們對原型對象所做的任何修改都能立即從實例中反應(yīng)出來——即使是先創(chuàng)建實例后修改原型。
不信你看:
var friend = new Person(); Person.prototype.sayHi = function(){ alert("hi"); }; friend.sayHi(); // "hi"
這個可以歸結(jié)于實例與原型之間的松散鏈接關(guān)系。我們首先會在實例中搜索sayHi的屬性,在沒找到的情況下會繼續(xù)搜索原型,因為實例與原型之間的鏈接只不過是一個指針。
但是如果重寫整個原型對象,情況就不一樣了。調(diào)用構(gòu)造函數(shù)時會為實例添加一個指向最初原型的[[Prototype]]指針,而把原型修改為另外一個對象就等于切斷了構(gòu)造函數(shù)與最初原型之間的聯(lián)系。
請記住,實例中的指針僅指向原型,而不指向構(gòu)造函數(shù)。
function Person(){ } var friend = new Person(); Person.prototype = { constructor:Person, name : "Simon", job : "software Engineer", sayName : function () { alert(this.name); } }; friend.sayName(); //error
在這個例子中,我們創(chuàng)建了Person的實例,然后又重寫了其原型對象,然后在調(diào)用sayName()時發(fā)生錯誤,因此friend指向的原型不包含以該名字命名的屬性。
省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實例在默認情況下都取得相同的屬性值。
共享導(dǎo)致的問題,很多屬性可以共享,對于包含引用類型值的屬性來說,問題比較突出。
function Person(){
} Person.prototype = { constructor:Person, name : "Simon", 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 === person2.friends) // true;
修改person1.friends 引用的數(shù)組,添加字符串,由于 friends數(shù)組存在 Person.prototype 而非 person1中,所以修改也會造成person2.friends反映出來,如果我們的初衷就是要共享同一個數(shù)組,那無話可說。
可是一般都是要有屬于自己的全部屬性的。而這個問題正是我們很少看到有人多帶帶使用原型模式的原因。
組合使用構(gòu)造函數(shù)模式和原型模式創(chuàng)建自定義類型的最常見方式就是這個。構(gòu)造函數(shù)用于定義實例屬性,原型模式用于定義方法和共享的屬性。這樣,每個實例都會有自己的一份實例屬性的副本,但又同事共享著對方法的引用,最大限度節(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,Court,Van alert(person2.friends); // shelby,Court alert(person1.friends === person2.friends); // false alert(person1.sayName === person2.sayName); // true
實例屬性都是在構(gòu)造函數(shù)中定義的,所有實例共享的屬性是在 constructor 和方法sayName()是在原型中定義的。
動態(tài)原型模式當(dāng)其他OO語言經(jīng)驗開發(fā)人員看到獨立的構(gòu)造函數(shù)和原型時,會感到困惑。因此出現(xiàn)了 動態(tài)原型模式———即把所有信息都封裝在了構(gòu)造函數(shù)中,而通過在構(gòu)造函數(shù)中初始化原型(僅在必要的情況下),又保持了同事使用構(gòu)造函數(shù)和原型的優(yōu)點。
換句話說,可以通過檢查某個應(yīng)該存在的方法是否有效,來決定是否需要初始化原型。
function Person (name, age, job){ //屬性 this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; if( typeof this.sayName != "function"){ Person.prototype.sayName = function() { alert(this.name); }; } } // 只有在sayName不存在的情況下, 才將其添加到原型中,這段代碼只會在初次調(diào)用函數(shù)時執(zhí)行。此后原型已經(jīng)完成初始化,不需要再做修改。 var friends1 = new Person("Nicholas", 29, "software Engineer"); var friends2 = new Person("Zaynex",19,"Engineer"); friends1.sayName(); friends2.sayName();
由于第一次當(dāng)friends1初始化之后,friends2就不需要再進行初始化原型。
詳情參考點擊此處
在上述幾種模式都不適用的情況下,我們可以使用寄生構(gòu)造函數(shù)模式。
基本思想:創(chuàng)建一個函數(shù),該函數(shù)的作用僅僅是封裝對象的代碼,然后再返回新創(chuàng)建的對象。
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òu)造函數(shù)應(yīng)用
在特殊情況下為對象創(chuàng)建構(gòu)造函數(shù)。 假設(shè)我們想創(chuàng)建一個具有額外方法的特殊數(shù)組,由于不能直接修改Array構(gòu)造函數(shù),因此可以使用這個模式。
function SpecialArray(){ var values = new Array(); values.push.apply(values, arguments); values.toPipedString = function(){ return this.join("|"); } return values; } var colors = new SpecialArray("red", "blue", "green"); alert(colors.toPipedString()); // red|blue|green
寄生構(gòu)造函數(shù)模式:返回的對象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性沒有關(guān)系;不能依賴于 instanceof操作符確定對象類型。因此不建議在已使用其他模式的情況下使用該種模式。
穩(wěn)妥構(gòu)造函數(shù)模式 應(yīng)用場景穩(wěn)妥對象,是指沒有公共屬性,其方法也不引用this的對象。適合在安全環(huán)境下(這些環(huán)境會禁止使用this 和 new),或者放置數(shù)據(jù)被其他應(yīng)用程序改動時使用。
穩(wěn)妥函數(shù)與寄生構(gòu)造函數(shù)差異新創(chuàng)建的對象的實例方法不引用this。
不使用new 操作符調(diào)用構(gòu)造函數(shù)。
function Person(name, age, job) {
var o = new Object(); //可以在這里定義私有變量和函數(shù)。 // //添加方法 o.sayName = function(){ alert(name); }; //返回對象 return o;
}
var friend = Person("Nicholas", 29, "software Engineer");
friend.sayName();
以這種模式創(chuàng)建的對象,除了使用sayName()方法以外,沒有其他辦法訪問name的值。
與計生構(gòu)造函數(shù)模式類似,使用穩(wěn)妥構(gòu)造函數(shù)模式創(chuàng)建的對象與構(gòu)造函數(shù)之間沒有什么關(guān)系,因此instanceof操作符對這種對象沒有意義。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/86385.html
摘要:在上百種語言中算是命好的一個,還有就是最近納入高考體系的。由以下三個部分構(gòu)成。就是對實現(xiàn)該標(biāo)準規(guī)定的各個方面內(nèi)容的語言的描述。是針對但經(jīng)過擴展的用于的應(yīng)用程序編程接口。將頁面映射為由節(jié)點構(gòu)成的樹狀結(jié)構(gòu)。 JavaScript的歷史這里就不再贅述了,當(dāng)然JavaScript的歷史還是比較有意思的。在上百種語言中JavaScript算是‘命’好的一個,還有就是最近納入高考體系的python...
摘要:數(shù)據(jù)類型中有種簡單數(shù)據(jù)類型也稱為基本數(shù)據(jù)類型和。在中非空字符串,非零數(shù)字,任意對象,都被認為。而空字符串,和,,認為是。用于表示整數(shù)和浮點數(shù)。標(biāo)識符由數(shù)字字母下劃線美元符組成,但首字母不能是數(shù)字。變量方法對象命名推薦駝峰法。 JavaScript語法 一.語法簡介 因為JavaScript語法和Java等語法非常類似。所以只是簡單介紹一下。 大小寫 JavaScript是大小寫敏感的語...
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響年是向上的一年在新的城市穩(wěn)定連續(xù)堅持健身三個月早睡早起游戲時間大大縮減,學(xué)會生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響2018年是向上的一年:在新的城市穩(wěn)定、...
摘要:可以使用偵聽器或處理程序來預(yù)訂事件,以便事件發(fā)生時執(zhí)行相應(yīng)的代碼。響應(yīng)某個事件的函數(shù)稱為事件處理程序或事件偵聽器??梢詣h除通過級方法指定的事件處理程序。 JavaScript和HTML之間的交互是通過事件實現(xiàn)的。 事件:文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間。 可以使用偵聽器(或處理程序來預(yù)訂事件),以便事件發(fā)生時執(zhí)行相應(yīng)的代碼。 1. 事件流 事件流:從頁面中接收事件的順序。 ...
摘要:全局執(zhí)行環(huán)境的變量對象始終是作用域鏈中的最后一個變量對象。綜上,每個函數(shù)對應(yīng)一個執(zhí)行環(huán)境,每個執(zhí)行環(huán)境對應(yīng)一個變量對象,而多個變量對象構(gòu)成了作用域鏈,如果當(dāng)前執(zhí)行環(huán)境是函數(shù),那么其活動對象在作用域鏈的前端。 1.幾個概念 先說幾個概念:函數(shù)、執(zhí)行環(huán)境、變量對象、作用域鏈、活動對象。這幾個東東之間有什么關(guān)系呢,往下看~ 函數(shù) 函數(shù)大家都知道,我想說的是,js中,在函數(shù)內(nèi)部有兩個特殊...
摘要:實現(xiàn)原型鏈的方式如下讓原型對象稱為另一個構(gòu)造函數(shù)的實例這個實例繼承了的屬性上述代碼繼承是通過來實現(xiàn),創(chuàng)建的實例,并將該實例賦給。無疑,集兩者之大成,這才是最常用的繼承模式。 原型鏈 JavaScript的繼承主要依靠原型鏈來實現(xiàn)的。我們知道,構(gòu)造函數(shù),原型,和實例之間的關(guān)系:每個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針,而實例都包含一個原型對象的指針。 實現(xiàn)原型鏈...
閱讀 3129·2023-04-26 01:49
閱讀 2161·2021-10-13 09:39
閱讀 2396·2021-10-11 11:09
閱讀 983·2019-08-30 15:53
閱讀 2875·2019-08-30 15:44
閱讀 1013·2019-08-30 11:12
閱讀 3063·2019-08-29 17:17
閱讀 2442·2019-08-29 16:57