【譯】JavaScript 代碼整潔之道-變量篇

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文源於翻譯 ","attrs":{}},{"type":"link","attrs":{"href":"https://dev.to/carlillo/clean-code-applied-to-javascript-part-ii-variables-pc","title":"","type":null},"content":[{"type":"text","text":"Clean Code Applied to JavaScript — Part II. Variables","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這篇文章是 “代碼整潔” 系列中的一篇,這一系列文章都在探討如何編寫 JavaScript 整潔代碼。在本系列的文章中,我們將討論程序員都應知應會的、應用於 JavaScript/TypeScript 語言的代碼整潔之道。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"簡介","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這篇文章中,我們將介紹書寫整潔代碼的基本技巧和建議,並重點關注於代碼中的最基本的元素 -- ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"變量","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文中所有示例都是用 JavaScript 來實現,但是這些良好的實踐適用於任何編程語言,包括 “最接近硬件”(","attrs":{}},{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Close_to_Metal","title":"","type":null},"content":[{"type":"text","text":"CTM","attrs":{}}]},{"type":"text","text":") 的編程語言。爲什麼要特別強調這一點呢?曾經和同事討論過,他們在工作中使用 C 或 Go 語言做開發,但是並不喜歡將這些實踐應用於開發中,他們甚至認爲在他們使用的編程語言中 “沒有人” 會這樣做。然後我的回答是,只有行動起來纔能有所改變。儘管如此,我們還是對這些實踐的優缺點做了較長時間的討論。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我們開始介紹如何將這些技巧應用在程序中的變量上。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"變量名要名副其實","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"變量的名稱必須能夠描述出該變量的作用和用途。也就是說,我們不應該用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"x","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"y","attrs":{}}],"attrs":{}},{"type":"text","text":" 這樣的名字去作爲變量名,除非我們正在開發數學軟件,在數學的語境中,這些名字是準確的。在其他的情況下,應該避免使用這種變量名,因爲它無法描述出該變量的真實用途,使代碼難於理解。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先,如果我們調用一個名字爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"x","attrs":{}}],"attrs":{}},{"type":"text","text":" 的變量,我們能否立刻知道它用來做什麼事情嗎?不能!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其次,我們繼續保留名稱,併爲它添加註釋。不過我們爲什麼要給一個不規範的變量名去添加註釋呢? 很顯然,這個問題有更簡單的解決方案,那就是給變量取一個合適的名稱。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"現在有趣的事情來了,父母給孩子起個名字需要多久?與之類似,要找到合適的變量名稱,我們同樣需要很長時間。但最重要的是,在 IDE 的支持下,我們可以不斷地重命名變量,直到找到一個更恰當的名稱。選個好名字需要花時間,但磨刀不誤砍柴工,簡單易懂的名字讓我們很輕易的知道發生了什麼。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const x; // What it is?!\nconst x; // User information\n\n\nconst user;\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"變量名可以讀出來","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果一個變量的名字有意義,最好的一點就是我們能夠把它的發音讀出來。回到整潔代碼的重要實踐之一,即生成人類可讀的代碼,我認爲能夠讀出變量的發音是必要的。因此,在這種場合不應該使用首字母縮略詞,即使它們看起來非常的巧妙。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在選擇變量的名稱時,另一個錯誤的行爲是刪除一個詞中某些字母,使用這些縮略語讀起來很困難。首先,我們是在用英語編碼,而且不是所有的開發者都是講英語的。因此,我們爲什麼要把它的名字減少 3 或 4 個字符?這有什麼好處呢?代碼會被工具(轉譯器包括其他語言的編譯器)操作,最終正確地完成格式化(使用 Prettier)。因此,把不能發音的名字放在一起,只能讓我們更費力地去推斷變量的用途。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"請不要讓我思考那些不是業務邏輯重點的事情!!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看看下面的第一段代碼,你可能會推斷出該類正在創建的數據類型,但這很考驗團隊同事之間的默契度。在第二段代碼中,它定義了同樣的數據,但不需要花費任何腦力就能讓人知道變量的用途。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"class DtaRcrd102 {\n private Date genymdhms;\n private Date modymdhms;\n}\n\n\nclass Customer {\n private Date generationTimestamp;\n private Date modificationTimestamp;\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"不要在名稱中使用變量的類型","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在變量名稱中使用數據類型作爲前綴是一個很古老的做法,現在讓我們反思一下這個問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"變量名稱中必須要用類型作爲前綴嗎?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每個公司和工程都有各自的前綴規範,那如何去學習和書寫這種代碼呢?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我在變量的名稱中使用一種編程語言的類型系統,爲什麼要用它呢?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當變量的數據類型發生變化時,比如把 Array 修改爲 Map,這種情況怎麼處理?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個前綴能給我們帶來什麼?它是可以發音的嗎?","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們的語言是類型化的,我們爲什麼要有這個前綴呢?但是,即使這個語言沒有被類型化,就像發生在 JavaScript 中的那樣。我們在變量的名稱中揭示了一個具體的實現,它將我們與數據的類型相聯繫。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,我們正在將數據類型與業務邏輯關聯到了一起。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"這是毫無意義的!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"恰恰相反,它使變量無法發音,如果我們進行改進(使我們的代碼適應新的數據類型),我們就必須重新命名所有的代碼。也就是說,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"這個前綴是噪音","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看一下變量定義中的兩個例子。作爲一個開發者,你真的有必要使用這個前綴來理解變量的內容嗎?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const aCountries = [];\nconst sName = '';\nconst dAmount = 3.2;\n\n\nconst countries = [];\nconst name = '';\nconst amount = 3.2;\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"對同一類型的變量使用相同的詞彙表","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個建議並不專門針對團隊內工作的時候,即使在單獨生成代碼的時候也會有類似情況發生。尤其是在我們作爲軟件開發者的職業生涯的開始階段。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對同一類型的數據使用相同的詞彙表。如果我們需要檢索一個用戶或客戶的信息,我們不能以不同的方式稱呼用戶或客戶。也就是說,不能有時稱其爲 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"user","attrs":{}},{"type":"text","text":",有時稱其爲 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"customer","attrs":{}},{"type":"text","text":",甚至是 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"client","attrs":{}},{"type":"text","text":" 這個詞。更不可取的是,在變量名稱上額外再加一個後綴。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,在軟件開發中,要對行業術語和名詞詞彙進行統一的規範或定義。特別是在團隊開發時,這個規範或定義尤爲重要,避免讓一羣開發者用不同的名字來指代同一個概念。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面的代碼就是很好的示例。同一個概念,有三個不同的定義。必須自始至終使用統一的命名,不管是 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"user","attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"customer","attrs":{}},{"type":"text","text":" 還是 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"client","attrs":{}},{"type":"text","text":",只能用同一個。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"getUserInfo();\ngetClientData();\ngetCustomerRecord();\n\n\ngetUser();\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"不要添加不需要的上下文","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在變量名稱中沒有必要添加類或包的相關上下文。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在變量名稱中添加上下文是很常見的,這樣可以知道這個變量位於哪個工作區。事實上,當我們閱讀代碼時,會很快意識到這是完全沒有必要的。在理解代碼的過程中,這些不必要的冗餘會帶來一些干擾。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在下面的例子中,定義了一個汽車 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Car","attrs":{}}],"attrs":{}},{"type":"text","text":",有三個基本屬性和一個方法。在變量包含了上下文的情況下,我們可以觀察到 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"car","attrs":{}},{"type":"text","text":" 這個詞不斷的重複,並且沒有任何作用。如果我們去掉 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"car","attrs":{}},{"type":"text","text":" 這個詞(上下文),代碼也完全可以被理解;事實上,由於我們去掉了這些噪音,代碼會變得更容易理解。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const Car = {\n carMake: 'Honda',\n carModel: 'Accord',\n carColor: 'Blue',\n};\n\nfunction paintCar(car) {\n car.carColor = 'Red';\n}\n\n\nconst Car = {\n make: 'Honda',\n model: 'Accord',\n color: 'Blue',\n};\n\nfunction paint(car) {\n car.color = 'Red';\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"不要使用魔法數字和字符串","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在編寫代碼時,不應該在源代碼中直接使用數字或文本字符串,這些通常也被稱爲魔法數字。這個數字是什麼意思?必須要解釋這個數字嗎?這讓我們不得不思考業務邏輯之外的事情。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,這些魔法數字或字符串必須存儲在常量中,通過對常量的名稱來表達出它們的用途。在業務邏輯層面上,對於那些有意義的數字或文本字符串,如果沒有一個確切的名字就會引起噪音。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面的例子中,莫名其妙出現的數字 86400000,會讓人丈二和尚 -- 摸不着頭腦。此外,文本字符串也是危險的,譬如在多次書寫 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"Administrator","attrs":{}},{"type":"text","text":" 過程中,如果某次將其誤寫爲 ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"Adminitrator","attrs":{}},{"type":"text","text":" 導致代碼發生問題,卻不易排出錯誤。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"// What the heck is 86400000 for?\nsetTimeout(blastOff, 86400000);\nuser.rol = 'Administrator';\n\n\nconst MILLISECONDS_IN_A_DAY = 86400000;\nconst ADMINISTRATOR_ROL = 'Administrator';\n\nsetTimeout(blastOff, MILLISECONDS_IN_A_DAY);\nuser.rol = ADMINISTRATOR_ROL;\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"結論","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在我們剛開始成爲一名開發人員的時候,我們可能不會注意到變量的名稱,因爲通常我們剛開始開發腳本或代碼的時候都是在獨自工作。並且我們的關注點都是如何編寫代碼,一旦項目被開發出來之後,我們就不會再閱讀自己的源代碼。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然而,當我們開發一個需要花費相當長時間維護的軟件時,我們就需要閱讀和重新讀取源代碼。這時,合理的命名變量將給我們帶來高質量的、整潔的代碼。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這篇文章中,我們回顧了給變量命名時的一些基本要點。如果你正在學習編程,把它們寫下來,因爲在未來它們將爲你節省許多精力。如果你有一個漫長的職業生涯,你會發現,通過不斷地閱讀代碼,你自然而然地就會得出了這些結論。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"請記住,我們討論的要點如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"變量名要名副其實","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"變量名可以讀出來","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不要在名稱中使用變量的類型","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對同一變量的類型使用相同的詞彙","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不要添加不需要的上下文","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不要使用魔法數字和字符串","attrs":{}}]}]}],"attrs":{}},{"type":"horizontalrule","attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關注公衆號 “","attrs":{}},{"type":"link","attrs":{"href":"https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f37bc98a8bae45269ca7982cbb0d344a~tplv-k3u1fbpfcp-zoom-1.image","title":"","type":null},"content":[{"type":"text","text":"KooFE前端團隊","attrs":{}}]},{"type":"text","text":"” 回覆 「JavaScript整潔代碼」有機會獲得 ","attrs":{}},{"type":"link","attrs":{"href":"https://book.douban.com/subject/4199741/","title":"","type":null},"content":[{"type":"text","text":"代碼整潔之道","attrs":{}}]},{"type":"text","text":" 圖書一本。","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章