前端面試基礎篇 一(附答案)

1. 說一下http和https

答:

http: 超文本傳輸協議,是一個客戶端和服務器端請求和應答的標準(TCP)。

https: 是HTTP下加入SSL層,HTTPS的安全基礎是SSL。

區別:http的連接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全,HTTP 的端口號是 80,HTTPS 是 443

 

2. tcp三次握手,一句話概括

答: 

S代表服務器, C代表客戶端

第一次握手:S只可以確認 自己可以接受C發送的報文段   

第二次握手:C可以確認 S收到了自己發送的報文段,並且可以確認 自己可以接受S發送的報文段

第三次握手:S可以確認 C收到了自己發送的報文段

 

3.幾個很實用的BOM屬性對象方法?

答:

什麼是Bom? Bom是瀏覽器對象

(1)location對象

location.href-- 返回或設置當前文檔的URL
location.search -- 返回URL中的查詢字符串部分。例如 http://www.dreamdu.com/dreamdu.php?id=5&name=dreamdu 返回包括(?)後面的內容?id=5&name=dreamdu
location.hash -- 返回URL#後面的內容,如果沒有#,返回空
location.host -- 返回URL中的域名部分,例如www.dreamdu.com
location.hostname -- 返回URL中的主域名部分,例如dreamdu.com
location.pathname -- 返回URL的域名後的部分。例如 http://www.dreamdu.com/xhtml/ 返回/xhtml/
location.port -- 返回URL中的端口部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回8080
location.protocol -- 返回URL中的協議部分。例如 http://www.dreamdu.com:8080/xhtml/ 返回(//)前面的內容http:
location.assign -- 設置當前文檔的URL
location.replace() -- 設置當前文檔的URL,並且在history對象的地址列表中移除這個URL location.replace(url);
location.reload() -- 重載當前頁面

(2)history對象

history.go() -- 前進或後退指定的頁面數 history.go(num);
history.back() -- 後退一頁
history.forward() -- 前進一頁

(3)Navigator對象

navigator.userAgent -- 返回用戶代理頭的字符串表示(就是包括瀏覽器版本信息等的字符串)   ua
navigator.cookieEnabled -- 返回瀏覽器是否支持(啓用)cookie

 

4.介紹知道的http返回的狀態碼

答:

100    Continue    繼續。客戶端應繼續其請求

101    Switching Protocols    切換協議。服務器根據客戶端的請求切換協議。只能切換到更高級的協議,例如,切換到HTTP的新版本協議

200    OK    請求成功。一般用於GET與POST請求

201    Created    已創建。成功請求並創建了新的資源

202    Accepted    已接受。已經接受請求,但未處理完成

203    Non-Authoritative Information    非授權信息。請求成功。但返回的meta信息不在原始的服務器,而是一個副本

204    No Content    無內容。服務器成功處理,但未返回內容。在未更新網頁的情況下,可確保瀏覽器繼續顯示當前文檔

205    Reset Content    重置內容。服務器處理成功,用戶終端(例如:瀏覽器)應重置文檔視圖。可通過此返回碼清除瀏覽器的表單域

206    Partial Content    部分內容。服務器成功處理了部分GET請求

300    Multiple Choices    多種選擇。請求的資源可包括多個位置,相應可返回一個資源特徵與地址的列表用於用戶終端(例如:瀏覽器)選擇

301    Moved Permanently    永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。今後任何新的請求都應使用新的URI代替

302    Found    臨時移動。與301類似。但資源只是臨時被移動。客戶端應繼續使用原有URI

303    See Other    查看其它地址。與301類似。使用GET和POST請求查看

304    Not Modified    未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之後修改的資源

305    Use Proxy    使用代理。所請求的資源必須通過代理訪問

306    Unused    已經被廢棄的HTTP狀態碼

307    Temporary Redirect    臨時重定向。與302類似。使用GET請求重定向

400    Bad Request    客戶端請求的語法錯誤,服務器無法理解

401    Unauthorized    請求要求用戶的身份認證

402    Payment Required    保留,將來使用

403    Forbidden    服務器理解請求客戶端的請求,但是拒絕執行此請求

404    Not Found    服務器無法根據客戶端的請求找到資源(網頁)。通過此代碼,網站設計人員可設置"您所請求的資源無法找到"的個性頁面

405    Method Not Allowed    客戶端請求中的方法被禁止

406    Not Acceptable    服務器無法根據客戶端請求的內容特性完成請求

407    Proxy Authentication Required    請求要求代理的身份認證,與401類似,但請求者應當使用代理進行授權

408    Request Time-out    服務器等待客戶端發送的請求時間過長,超時

409    Conflict    服務器完成客戶端的PUT請求是可能返回此代碼,服務器處理請求時發生了衝突

410    Gone    客戶端請求的資源已經不存在。410不同於404,如果資源以前有現在被永久刪除了可使用410代碼,網站設計人員可通過301代碼指定資源的新位置

411    Length Required    服務器無法處理客戶端發送的不帶Content-Length的請求信息

412    Precondition Failed    客戶端請求信息的先決條件錯誤

413    Request Entity Too Large    由於請求的實體過大,服務器無法處理,因此拒絕請求。爲防止客戶端的連續請求,服務器可能會關閉連接。如果只是服務器暫時無法處理,則會包含一個Retry-After的響應信息

414    Request-URI Too Large    請求的URI過長(URI通常爲網址),服務器無法處理

415    Unsupported Media Type    服務器無法處理請求附帶的媒體格式

416    Requested range not satisfiable    客戶端請求的範圍無效

417    Expectation Failed    服務器無法滿足Expect的請求頭信息

500    Internal Server Error    服務器內部錯誤,無法完成請求

501    Not Implemented    服務器不支持請求的功能,無法完成請求

502    Bad Gateway    作爲網關或者代理工作的服務器嘗試執行請求時,從遠程服務器接收到了一個無效的響應

503    Service Unavailable    由於超載或系統維護,服務器暫時的無法處理客戶端的請求。延時的長度可包含在服務器的Retry-After頭信息中

504    Gateway Time-out    充當網關或代理的服務器,未及時從遠端服務器獲取請求

505    HTTP Version not supported    服務器不支持請求的HTTP協議的版本,無法完成處理

 

5.fetch發送2次請求的原因

答:

fetch發送post請求的時候,總是發送2次,第一次狀態碼是204,第二次才成功?

原因很簡單,因爲你用fetch的post請求的時候,導致fetch 第一次發送了一個Options請求,詢問服務器是否支持修改的請求頭,如果服務器支持,則在第二次中發送真正的請求。

 

6.click在ios上有300ms延遲,原因及如何解決

答:

<meta name="viewport" content="width=device-width, user-scalable=no">

 

7.說一下瀏覽器緩存

答:

緩存分爲兩種:強緩存和協商緩存,根據響應的header內容來決定。

強緩存相關字段有expires,cache-control。如果cache-control與expires同時存在的話,cache-control的優先級高於expires。

協商緩存相關字段有Last-Modified/If-Modified-Since,Etag/If-None-Match

 

8.在地址欄裏輸入一個URL,到這個頁面呈現出來,中間會發生什麼?

答:

輸入url後,首先需要找到這個url域名的服務器ip,爲了尋找這個ip,瀏覽器首先會尋找緩存,查看緩存中是否有記錄,緩存的查找記錄爲:瀏覽器緩存-》系統緩存-》路由器緩存,緩存中沒有則查找系統的hosts文件中是否有記錄,如果沒有則查詢DNS服務器,得到服務器的ip地址後,瀏覽器根據這個ip以及相應的端口號,構造一個http請求,這個請求報文會包括這次請求的信息,主要是請求方法,請求說明和請求附帶的數據,並將這個http請求封裝在一個tcp包中,這個tcp包會依次經過傳輸層,網絡層,數據鏈路層,物理層到達服務器,服務器解析這個請求來作出響應,返回相應的html給瀏覽器,因爲html是一個樹形結構,瀏覽器根據這個html來構建DOM樹,在dom樹的構建過程中如果遇到JS腳本和外部JS連接,則會停止構建DOM樹來執行和下載相應的代碼,這會造成阻塞,這就是爲什麼推薦JS代碼應該放在html代碼的後面,之後根據外部央視,內部央視,內聯樣式構建一個CSS對象模型樹CSSOM樹,構建完成後和DOM樹合併爲渲染樹,這裏主要做的是排除非視覺節點,比如script,meta標籤和排除display爲none的節點,之後進行佈局,佈局主要是確定各個元素的位置和尺寸,之後是渲染頁面,因爲html文件中會含有圖片,視頻,音頻等資源,在解析DOM的過程中,遇到這些都會進行並行下載,瀏覽器對每個域的並行下載數量有一定的限制,一般是4-6個,當然在這些所有的請求中我們還需要關注的就是緩存,緩存一般通過Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的區別在於Cache-Control使用相對時間,Expires使用的是基於服務器 端的絕對時間,因爲存在時差問題,一般採用Cache-Control,在請求這些有設置了緩存的數據時,會先 查看是否過期,如果沒有過期則直接使用本地緩存,過期則請求並在服務器校驗文件是否修改,如果上一次 響應設置了ETag值會在這次請求的時候作爲If-None-Match的值交給服務器校驗,如果一致,繼續校驗 Last-Modified,沒有設置ETag則直接驗證Last-Modified,再決定是否返回304

 

9.畫一條0.5px的線

答:

採用meta viewport的方式

<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

採用border-image的方式

採用transform: scale()的方式

 

10.垂直居中的方法

答:

margin:auto法

margin負值法

利用flex

 

11.浮動清除

答:

方法一:使用帶clear屬性的空元素

在浮動元素後使用一個空元素如<div class="clear"></div>,並在CSS中賦予.clear{clear:both;}屬性即可清理浮動。亦可使用<br class="clear" />或<hr class="clear" />來進行清理。

方法二:使用CSS的overflow屬性

給浮動元素的容器添加overflow:hidden;或overflow:auto;可以清除浮動,另外在 IE6 中還需要觸發 hasLayout ,例如爲父元素設置容器寬高或設置 zoom:1。

在添加overflow屬性後,浮動元素又回到了容器層,把容器高度撐起,達到了清理浮動的效果。

方法三:給浮動的元素的容器添加浮動

給浮動元素的容器也添加上浮動屬性即可清除內部浮動,但是這樣會使其整體浮動,影響佈局,不推薦使用。

方法四:使用鄰接元素處理

什麼都不做,給浮動元素後面的元素添加clear屬性。

方法五:使用CSS的:after僞元素

結合:after 僞元素(注意這不是僞類,而是僞元素,代表一個元素之後最近的元素)和 IEhack ,可以完美兼容當前主流的各大瀏覽器,這裏的 IEhack 指的是觸發 hasLayout。

給浮動元素的容器添加一個clearfix的class,然後給這個class添加一個:after僞元素實現元素末尾添加一個看不見的塊元素(Block element)清理浮動。

參考https://www.cnblogs.com/ForEvErNoME/p/3383539.html

 

12.calc屬性

答:

Calc用戶動態計算長度值,任何長度值都可以使用calc()函數計算,需要注意的是,運算符前後都需要保留一個空格,例如:width: calc(100% - 10px);

 

13.瞭解重繪和重排嗎,知道怎麼去減少重繪和重排嗎,讓文檔脫離文檔流有哪些方法

答:

DOM的變化影響到了預算內宿的幾何屬性比如寬高,瀏覽器重新計算元素的幾何屬性,其他元素的幾何屬性也會受到影響,瀏覽器需要重新構造渲染書,這個過程稱之爲重排,瀏覽器將受到影響的部分重新繪製在屏幕上 的過程稱爲重繪,引起重排重繪的原因有:

添加或者刪除可見的DOM元素,

元素尺寸位置的改變

瀏覽器頁面初始化,

瀏覽器窗口大小發生改變,重排一定導致重繪,重繪不一定導致重排,

減少重繪重排的方法有:

不在佈局信息改變時做DOM查詢,

使用csstext,className一次性改變屬性

使用fragment

對於多次重排的元素,比如說動畫。使用絕對定位脫離文檔流,使其不影響其他元素

 

14.說一下閉包

答:

閉包就是能夠讀取其他函數內部變量的函數,或者子函數在外調用,子函數所在的父函數的作用域不會被釋放。

 

15.說說前端中的事件流

答:

什麼是事件流:事件流描述的是從頁面中接收事件的順序,DOM2級事件流包括下面幾個階段。

事件捕獲階段

處於目標階段

事件冒泡階段

addEventListener:addEventListener 是DOM2 級事件新增的指定事件處理程序的操作,這個方法接收3個參數:要處理的事件名、作爲事件處理程序的函數和一個布爾值。最後這個布爾值參數如果是true,表示在捕獲階段調用事件處理程序;如果是false,表示在冒泡階段調用事件處理程序。

IE只支持事件冒泡

 

16.說一下事件委託

答:

簡介:事件委託指的是,不在事件的發生地(直接dom)上設置監聽函數,而是在其父元素上設置監聽函數,通過事件冒泡,父元素可以監聽到子元素上事件的觸發,通過判斷事件發生元素DOM的類型,來做出不同的響應。

舉例:最經典的就是ul和li標籤的事件監聽,比如我們在添加事件時候,採用事件委託機制,不會在li標籤上直接添加,而是在ul父元素上添加。

好處:比較合適動態元素的綁定,新添加的子元素也會有監聽函數,也可以有事件觸發機制。

 

17.懶加載怎麼實現

答:

1)利用intersection observer   (注意:Intersection observer目前只能在Chrome63+和firefox58+使用)

開發者只需要註冊一個observer去監控元素而不是寫一大堆亂七八糟的視窗檢測代碼。註冊observer之後我們只需要做的就是當元素可見時改變它的行爲

2)利用事件

你可以使用scrollresizeorientationchange事件,再配合getBoundingClientRectAPI就可以實現懶加載了

3)CSS圖像

思路是通過JavaScript檢測到元素處於視窗中時,加一個class類名,這個class就引用了外部圖片資源

參考https://www.jianshu.com/p/e86c61468285

 

18.改變函數內部this指針的指向函數(bind,apply,call的區別)

答:

call和apply都是對函數的直接調用,而bind方法返回的仍然是一個函數,因此後面還需要()來進行調用纔可以

通過apply和call改變函數的this指向,他們兩個函數的第一個參數都是一樣的表示要改變指向的那個對象,

第二個參數,apply是數組,而call則是arg1,arg2...這種形式。

xw.say.call(xh,"實驗小學","六年級")

xw.say.apply(xh,["實驗小學","六年級"])

參考https://www.cnblogs.com/cosiray/p/4512969.html

 

19. js的各種位置

答:

clientHeight:表示的是可視區域的高度,不包含border和滾動條

offsetHeight:表示可視區域的高度,包含了border和滾動條

scrollHeight:表示了所有區域的高度,包含了因爲滾動被隱藏的部分。

clientTop:表示邊框border的厚度,在未指定的情況下一般爲0

scrollTop:滾動後被隱藏的高度,獲取對象相對於由offsetParent屬性指定的父座標(css定位的元素或body元素)距離頂端的高度。

 

20.JS中的垃圾回收機制

答:

由於字符串、對象和數組沒有固定大小,所有當他們的大小已知時,才能對他們進行動態的存儲分配。JavaScript程序每次創建字符串、數組或對象時,解釋器都必須分配內存來存儲那個實體。只要像這樣動態地分配了內存,最終都要釋放這些內存以便他們能夠被再用,否則,JavaScript的解釋器將會消耗完系統中所有可用的內存,造成系統崩潰。

垃圾回收的方法:標記清除、計數引用。

1)標記清除

這是最常見的垃圾回收方式,當變量進入環境時,就標記這個變量爲”進入環境“,從邏輯上講,永遠不能釋放進入環境的變量所佔的內存,永遠不能釋放進入環境變量所佔用的內存,只要執行流程進入相應的環境,就可能用到他們。當離開環境時,就標記爲離開環境。

垃圾回收器在運行的時候會給存儲在內存中的變量都加上標記(所有都加),然後去掉環境變量中的變量,以及被環境變量中的變量所引用的變量(條件性去除標記),刪除所有被標記的變量,刪除的變量無法在環境變量中被訪問所以會被刪除,最後垃圾回收器,完成了內存的清除工作,並回收他們所佔用的內存。

2)引用計數法

另一種不太常見的方法就是引用計數法,引用計數法的意思就是每個值沒引用的次數,當聲明瞭一個變量,並用一個引用類型的值賦值給改變量,則這個值的引用次數爲1,;相反的,如果包含了對這個值引用的變量又取得了另外一個值,則原先的引用值引用次數就減1,當這個值的引用次數爲0的時候,說明沒有辦法再訪問這個值了,因此就把所佔的內存給回收進來,這樣垃圾收集器再次運行的時候,就會釋放引用次數爲0的這些值。

 

21.如何理解前端模塊化

答:

前端模塊化就是複雜的文件編程一個一個獨立的模塊,比如js文件等等,分成獨立的模塊有利於重用(複用性)和維護(版本迭代),這樣會引來模塊之間相互依賴的問題,所以有了commonJS規範,AMD,CMD規範等等,以及用於js打包(編譯等處理)的工具webpack

Commonjs:開始於服務器端的模塊化,同步定義的模塊化,每個模塊都是一個單獨的作用域,模塊輸出,modules.exports,模塊加載require()引入模塊。

AMD:中文名異步模塊定義的意思。

requireJS實現了AMD規範,主要用於解決下述兩個問題。

1.多個文件有依賴關係,被依賴的文件需要早於依賴它的文件加載到瀏覽器

2.加載的時候瀏覽器會停止頁面渲染,加載文件越多,頁面失去響應的時間越長。

語法:requireJS定義了一個函數define,它是全局變量,用來定義模塊。

 

22.對象深度克隆的簡單實現

function deepClone(obj){
    var newObj= obj instanceof Array ? []:{};
    for(var item in obj){
        var temple= typeof obj[item] == 'object' ? deepClone(obj[item]):obj[item];
        newObj[item] = temple;
    }
    return newObj;
}

 

23.實現一個once函數,傳入函數參數只執行一次

function ones(func){
    var tag=true;
    return function(){
        if(tag==true){
            func.apply(null,arguments);
            tag=false;
        }
        return undefined
    }
}

 

24.setTimeout、setInterval的區別

答:

setTimeout() 用於設定在指定的時間之後執行對應的函數或代碼,   一次

setInterval() 用於設定每隔指定的時間就執行對象的函數。    多次

 

25.實現一個兩列等高佈局,講講思路

答:

爲了實現兩列等高,可以給每列加上 padding-bottom:9999px;

margin-bottom:-9999px;同時父元素設置overflow:hidden;

 

26.數組常用方法

答:

1)會改變原來的數組,不會創建新數組

shift()  :刪除原數組第一項,並返回刪除元素的值,如果數組爲空則返回undefined。

unshift() :將參數添加到原數組開頭,並返回數組的長度。

pop() :刪除原數組最後一項,並返回刪除元素的值,如果數組爲空則返回undefined。

push() :將參數添加到原數組末尾,並返回數組的長度。

splice(index,howmany,item1,…..,itemX) :方法向/從數組中添加/刪除項目,然後返回被刪除的項目。index開始的下標,howmany刪除多少個,item1…itemx爲刪除後插入的元素。

reverse() :用於顛倒數組中元素的順序。

sort() :用於對數組的元素進行排序。參數可以爲函數

 

2)原數組無變化,返回新數組

concat() :返回一個新數組,數組合並,參數可以是具體的值,也可以是數組對象。可以是任意多個。

slice(start,end)  :方法可從已有的數組中返回選定的元素。返回一個新的數組,包含從 start 到 end (不包括該元素)的中的元素。

join() :用於把數組中的所有元素放入一個字符串,元素是通過指定的分隔符進行分隔的。

 

3)ES5的

filter()過濾 :

array.filter(function(currentValue,index,arr), thisObject ) 
參數說明: 
function: 要對每個數組元素執行的回調函數。 
function(currentValue,index,arr) 
currentValue:必須。當前元素的值 
index:可選。當期元素的索引值 
arr:可選。當期元素屬於的數組對象 
thisObject : 可選。在執行回調函數時定義的this對象。如果省略了 thisValue ,”this” 的值爲 “undefined”

對數組中的每個元素都執行一次指定的函數(callback),並且創建一個新的數組,該數組元素是所有回調函數執行時返回值爲 true 的原數組元素。它只對數組中的非空元素執行指定的函數,沒有賦值或者已經刪除的元素將被忽略,同時,新創建的數組也不會包含這些元素。

回調函數可以有三個參數:當前元素,當前元素的索引和當前的數組對象。

如參數 thisObject 被傳遞進來,它將被當做回調函數(callback)內部的 this 對象,如果沒有傳遞或者爲null,那麼將會使用全局對象。

filter 不會改變原有數組,記住:只有在回調函數執行前傳入的數組元素纔有效,在回調函數開始執行後才添加的元素將被忽略,而在回調函數開始執行到最後一個元素這一期間,數組元素被刪除或者被更改的,將以回調函數訪問到該元素的時間爲準,被刪除的元素將被忽略。

function isBigEnough(element){//判斷大於5的元素
    return (element>=5);
}
console.info(array);  //[1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 0, 33, 12]
console.info(array.filter(isBigEnough));//數組元素會依次傳人 [5, 6, 6, 7, 8, 9, 33, 12]
console.info(array);  //[1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 0, 33, 12]

map()處理 :

array.map(function(currentValue,index,arr), thisValue); 
map() 方法返回一個新數組,數組中的元素爲原始數組元素調用函數處理後的值。 
map() 方法按照原始數組元素順序依次處理元素。 
注意: map() 不會對空數組進行檢測。 
注意: map() 不會改變原始數組。

function sqrt(element){
    return element*element;
}
console.info(array);  //[1, 2, 3, 9, 0, 33, 12]
console.info(array.map(sqrt));  //[1, 4, 9, 81, 0, 1089, 144]
console.info(array);  //[1, 2, 3, 9, 0, 33, 12]

some()

方法用於檢測數組中的元素是否滿足指定條件(函數提供) 
如果有一個元素滿足條件,則表達式返回true , 剩餘的元素不會再執行檢測。 
如果沒有滿足條件的元素,則返回false。

function checknum(num) {
    return num >= 11;
}
console.info(array);  //[1, 2, 3, 9, 0]
console.info(array.some(checknum));  //false
array.push(11,12);
console.info(array);   //[1, 2, 3, 9, 0, 33, 12, 11, 12]
console.info(array.some(checknum));  //true

forEach()

forEach() 方法用於調用數組的每個元素,並將元素傳遞給回調函數。 
注意: forEach() 對於空數組是不會執行回調函數的。

lastIndexOf() :  (indexOf() 同理)

array.lastIndexOf(item,start) 
lastIndexOf() 方法可返回一個指定的字符串值最後出現的位置,在一個字符串中的指定位置從後向前搜索。 
如果要檢索的字符串值沒有出現,則該方法返回 -1。 
該方法將從尾到頭地檢索字符串 stringObject,看它是否含有子串 searchvalue。開始檢索的位置在字符串的 fromindex 處或字符串的結尾(沒有指定 fromindex 時)。如果找到一個 searchvalue,則返回 searchvalue 的第一個字符在 stringObject 中的位置。stringObject 中的字符位置是從 0 開始的。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple");//return 2

reduce()

reduce() 方法接收一個函數作爲累加器,數組中的每個值(從左到右)開始縮減,最終計算爲一個值。 
注意: reduce() 對於空數組是不會執行回調函數的。 
array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 
total 必需。初始值, 或者計算結束後的返回值。 
currentValue 必需。當前元素 
currentIndex 可選。當前元素的索引 
arr 可選。當前元素所屬的數組對象。

initialValue 可選。傳遞給函數的初始值

function getSum(total, num) {
    return total + num;
}
console.info(array);     //[1, 2, 3, 9, 0]
console.info(array.reduce(getSum));   //15
console.info(array);     //[1, 2, 3, 9, 0]

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章