多編程技術(shù)文章,請查閱IOKKS - 專業(yè)編程技術(shù)分享平臺
這并不是什么秘密,開發(fā)人員必須思考眾多日常任務(wù)。他們的一部分思考總是專注于各種例行事務(wù),比如“我應(yīng)該把這個函數(shù)放在哪個模塊?”,“我應(yīng)該如何命名這個變量?”,或者“這個變量應(yīng)該做什么?”盡管這些問題看起來簡單而瑣碎,但它們一直在消耗著心智資源。然而,如果有辦法通過自動化一些例行任務(wù)來簡化這個過程,從而將注意力集中在更為關(guān)鍵的事務(wù)上,那么利用這些方法無疑是明智的。
在這種情況下,命名約定起著至關(guān)重要的作用。了解并明智地應(yīng)用這些約定有助于增強代碼的可讀性,簡化理解,并減輕開發(fā)人員的認(rèn)知負(fù)擔(dān)。然而,并非所有開發(fā)人員都清楚并且有時會忘記如何正確應(yīng)用這些約定,盲目地將他們的注意力轉(zhuǎn)移到看似更為關(guān)鍵的事務(wù)上。這反過來使他們的代碼的可讀性和理解變得復(fù)雜,使表面上“更為關(guān)鍵”的任務(wù)比實際上可能更為復(fù)雜。
以下是我有機會參與的一個真實項目的截圖。請注意每個導(dǎo)入。根據(jù)名稱,嘗試猜測 我們可以從每個導(dǎo)入中獲得什么項目。
在本文中,我們將探討其中大部分內(nèi)容,學(xué)習(xí)或者提醒自己在編寫構(gòu)造時應(yīng)該遵循哪些原則。這將有助于你和未來與你的代碼一起工作的任何人,無論是你的團(tuán)隊還是你自己 在一段時間后,避免猜測 并增強你的代碼的可讀性。
本文將包括一系列命名建議。我不希望你將它們視為唯一的真理。首先,這并不完全正確,因為大多數(shù)建議都帶有一項免責(zé)聲明,暗示這些約定本身并不涵蓋所有情況。其次,雖然大多數(shù)建議在 JavaScript 社區(qū)中得到了接受,但并非所有人都出于各種原因遵循它們,有些建議被部分或者顯著修改以適應(yīng)特定團(tuán)隊。
本文的主要觀點是,每個項目都應(yīng)該建立自己的命名約定,無論它們是否與廣泛采用的約定一致,還是獨特于你的團(tuán)隊。關(guān)鍵的一點是要有約定并且遵守它們。
在互聯(lián)網(wǎng)上,有大量關(guān)于最佳命名實踐的文章。眾所周知的約定強調(diào),名稱應(yīng)該是簡短的,更重要的是,可理解的 。名稱應(yīng)該具體,與其使用的上下文相對應(yīng),并且一目了然地傳達(dá)代碼的含義。實際上,這些約定不僅可以而且應(yīng)該不僅在使用 JavaScript 時,而且在使用任何編程語言時都應(yīng)該被應(yīng)用。在這些通用規(guī)則中,我想重點關(guān)注一些約定中的特定細(xì)節(jié),這些約定是廣為人知的,但經(jīng)常被遺忘或者沒有完全遵守。
統(tǒng)一性 。在 JavaScript 項目中,有許多約定,但最有價值的約定是在單個項目中保持一致的編碼風(fēng)格。參與不同項目的個人最清楚不過,編寫風(fēng)格在不同項目之間可能會有顯著的差異。
通常會出現(xiàn)這樣的情況,即應(yīng)用的不同部分由不同團(tuán)隊開發(fā),或者在其開發(fā)中使用不同的技術(shù)。根據(jù)所選擇的編程語言或者開發(fā)團(tuán)隊的偏好,命名約定可能會有所不同。盡管存在這些差異,應(yīng)用的不同部分需要相互交互,比如前端和后端之間的數(shù)據(jù)交換。例如,從后端請求的數(shù)據(jù)的命名風(fēng)格可能與前端代碼中使用的風(fēng)格不同。
盡管 JavaScript 語言的約定是使用 camelCase,但值得注意的是,并沒有阻止使用,例如,snake_case。正如前面提到的,這種表示法對許多其他編程語言和一些團(tuán)隊來說可能更為熟悉。可能會出現(xiàn)這樣的情況,即與你的應(yīng)用程序風(fēng)格不同的命名風(fēng)格開始滲入你的代碼。
我們無權(quán)判斷使用不同的命名風(fēng)格是好是壞,因為各種原因可能推動這樣的選擇。然而,明確地混合兩種或更多種命名風(fēng)格可能會帶來挑戰(zhàn)。對于加入項目的新開發(fā)人員來說,理解正在發(fā)生的事情并決定使用哪種命名風(fēng)格可能會變得非常具有挑戰(zhàn)性。
// 不好
const hasAccess=checkHasUserAccess(session.current_user) && checkIsPageVisible(session.current_page)
// 好
const hasAccess=checkHasUserAccess(session.currentUser) && checkIsPageVisible(session.currentPage)
// 如果偏好這種命名風(fēng)格,也是好的
const has_access=check_has_user_access(session.current_user) && check_is_page_visible(session.current_page)
有幾種方法可以解決這個問題,從使用 解構(gòu)賦值、導(dǎo)入重命名、使用映射函數(shù)(例如 Array.prototype.map()),到更高級的方法,比如利用 適配器 設(shè)計模式。
關(guān)鍵在于采用一致的方法,不僅在命名約定上,而且在任務(wù)完成方式上也是如此。在可能的情況下,最好為特定操作選擇一種方法。避免強迫自己和其他開發(fā)人員花費時間和額外的心智資源來決定使用哪種方法。考慮委托這樣的任務(wù),特別是與編碼風(fēng)格相關(guān)的任務(wù),給工具。
僅限英文 。盡管在 JavaScript 中寫作時可以使用非拉丁字母,但不建議這樣做。即使你為自己編寫某些東西,每一行代碼都有“長壽”的能力,可能會有一天你需要與其他開發(fā)人員分享這些代碼。對于其他開發(fā)人員,尤其是來自不同國家的開發(fā)人員,理解代碼中發(fā)生的事情將會很困難。
在強調(diào)僅使用英文時,人們通常只考慮鍵盤布局。然而,人們不應(yīng)忘記縮寫和名稱的一般使用。它們應(yīng)該只與常用詞一起使用,比如 idx、err、evt、xhr、src 等社區(qū)中歷史上被接受的詞。在其他情況下,強烈不建議使用縮寫和詞語的簡寫,因為它們經(jīng)常會導(dǎo)致混淆,并且解密它們可能需要很長時間。
// 不好
const 新規(guī)ユーザーのウェルカムメッセージ='こんにちは'
const usrInf={ fName: 'John', lName: 'Doe' }
const isAdult=a >=18
// 好
const newUserWelcomeMessage='こんにちは'
const userInfo={ firstName: 'John', lastName: 'Doe' }
const isAdult=userAge >=18
還建議在代碼編輯器中啟用拼寫檢查器,它將突出顯示單詞中的語法錯誤。在許多編輯器中,默認(rèn)情況下已啟用,對于某些編輯器,你可能需要安裝一個擴展,比如 VS Code 的 Code Spell Checker。今天的拼寫檢查器足夠智能,大多數(shù)被廣泛接受的縮寫和詞語的簡寫不會被標(biāo)記為錯誤。
不僅僅是 camelCase 。許多資源強調(diào)在 JavaScript 中寫作時專門 使用 camelCase 表示法。然而,這并不完全準(zhǔn)確。建議更多地是關(guān)于遵循語言本身使用的表示法 。雖然 JavaScript 語言的大部分 是使用 camelCase 編寫的,但并非完全如此。以下是一些例子:
parseInt('18') // camelCase
new RegExp('[A-Z]', 'i') // PascalCase
Number.MAX_SAFE_INTEGER // PascalCase + UPPER_SNAKE_CASE
正如我們所看到的,JavaScript 不僅包括 camelCase 表示法,還包括其他一些表示法。JavaScript 中的所有類和構(gòu)造函數(shù)都是使用 PascalCase 表示法編寫的。在聲明自定義類和構(gòu)造函數(shù)時,習(xí)慣上要遵循與語言本身相同的命名約定。對于表示固定值的常量也是如此。無論是 JavaScript 內(nèi)置的常量還是開發(fā)人員創(chuàng)建的常量,通常都是以 UPPER_SNAKE_CASE 命名的。
與一些編程語言不同,其 API 使用各種表示法而沒有明確的分布不同,JavaScript 的 API 并不受此問題的困擾。因此,遵循語言本身中存在的約定是慣例。
遵循 readme.md 。假設(shè)你正在使用像 axios 這樣的網(wǎng)絡(luò)請求庫,并且該庫的 README 建議使用標(biāo)準(zhǔn)名稱 axios 進(jìn)行導(dǎo)入。
import httpRequester from 'npm:axios'
// 在文件的底部的某個地方
httpRequester('https://example.com')
將名稱從 axios 更改為 httpRequester 可能會導(dǎo)致混淆和錯誤,因為其他在項目中工作并期望標(biāo)準(zhǔn)名稱 axios 的開發(fā)人員可能會遇到問題。因此,遵循庫的 README 中設(shè)置的建議是非常重要的,以確保兼容性和代碼理解。
乍一看,使用 axios 庫的示例可能看起來無害,但類似的重命名場景可能會出現(xiàn)在更深度集成到項目中的更復(fù)雜的庫和框架的使用中。采用有意義的重命名實踐的團(tuán)隊將需要創(chuàng)建自己的文檔,因為新團(tuán)隊成員在官方文檔中找不到足夠的信息來理解技術(shù)的使用風(fēng)格的變化。
通常情況下,將更抽象的重命名用于與 依賴反轉(zhuǎn)原則 結(jié)合使用。然而,理解這里的微妙之處是很重要的。你和你的團(tuán)隊必須清楚地了解你正在做什么以及為什么,因為在采用這樣的實踐時需要保持平衡。
不包含數(shù)據(jù)類型 。在變量名稱中包含數(shù)據(jù)類型可能是誘人的,但屈服于這種誘惑通常會給名稱增加不必要的語義負(fù)荷。例如,對于包含數(shù)組的變量使用名稱 arr 可能會導(dǎo)致沖突,如果在其他地方使用相同名稱的變量。此外,名稱 arr 并不傳達(dá)有意義的信息。使名稱更具體,比如 userArr,是一種改進(jìn),但它并不能解決所有問題。
// 不好
const userNameMinLengthConst=3
const userObj=getUser()
const getUniqueUserNames=(arr)=> Array.from(new Set(arr))
// 好
const USER_NAME_MIN_LENGTH_COUNT=3
const user=getUser()
const getUniqueUserNames=(names)=> Array.from(new Set(names))
對于每種語言構(gòu)造,無論是內(nèi)置的還是自定義的數(shù)據(jù)結(jié)構(gòu),都存在一種傳統(tǒng)的方式來指示值的預(yù)期數(shù)據(jù)類型。這體現(xiàn)在構(gòu)造的名稱中,它應(yīng)該與社區(qū)內(nèi)部和團(tuán)隊內(nèi)部的約定一致。建議優(yōu)先考慮社區(qū)約定,因為解釋一些被廣泛接受的東西通常比引入完全獨特的東西更容易。在社區(qū)約定的情況下,你可以將某人引用到一篇互聯(lián)網(wǎng)文章,而對于團(tuán)隊特定的約定,你可能需要自己編寫這篇文章。
在本節(jié)中,我們將討論數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)的特定命名約定。雖然 JavaScript 在其內(nèi)置數(shù)據(jù)類型和結(jié)構(gòu)方面可能顯得有限,但它提供了廣泛的功能。這些功能包括各種方法,在其他編程語言中,這些方法通常被分隔成不同的內(nèi)置類型或數(shù)據(jù)結(jié)構(gòu)。
例如,在 JavaScript 中,對象可以用作 enum、map(dictionary)、graph 等。JavaScript 中的 number 數(shù)據(jù)類型包括處理整數(shù)和浮點數(shù)。根據(jù)具體要求,JavaScript 的數(shù)據(jù)類型和結(jié)構(gòu)可以靈活地適應(yīng)使用,為 JavaScript 提供了多樣性和強大性。
正是在這種情況下,命名約定的重要性變得明顯。它們不僅增強了代碼的可讀性,還在與代碼庫的其他部分交互時防止混淆和錯誤。良好的命名約定確保了代碼的清晰性,并有助于其他開發(fā)人員理解數(shù)據(jù)結(jié)構(gòu)及其目的,從而促進(jìn)團(tuán)隊內(nèi)更有效的協(xié)作。
布爾值 。布爾值的名稱應(yīng)以肯定前綴開頭,即前綴應(yīng)回答“是”的問題。雖然有幾個肯定的詞(should、can、will 等)可以回答“是”,但建議優(yōu)先選擇最常見的兩個詞——is 和 has。雖然使用其他肯定詞不會被視為錯誤,但應(yīng)將其視為例外情況,如果可能的話,最好避免使用它們。
這一約定的一個重要補充,經(jīng)常被忽視的是,肯定前綴不應(yīng)包括否定。其背后的原因是,否定運算符(!)最常用于布爾值。因此,一個命名為 isNotAllowed 的值,應(yīng)用了否定 !isNotAllowed,可能會相當(dāng)誤導(dǎo)。不相信嗎?那就試著快速弄清楚 !!isNotAllowed(雙重否定)等于什么。即使你能迅速做到,想象一下在整個文件中散布著所有這些否定反轉(zhuǎn)的真實代碼中工作。跟蹤這樣的邏輯,尤其是當(dāng)有很多邏輯時,可能會相當(dāng)具有挑戰(zhàn)性。在這種情況下,最好通過使用名稱中的積極肯定來改變評估布爾變量的邏輯。
函數(shù)和方法 。函數(shù)/方法的名稱應(yīng)該是一個動詞,并對應(yīng)它執(zhí)行的動作。
盡管函數(shù)/方法的命名約定乍看起來可能很簡單,但它們的命名是最有例外和其他約定的。對于大多數(shù)函數(shù)和方法,主要約定是名稱應(yīng)該是一個動詞,并對應(yīng)它們執(zhí)行的動作。
集合和迭代器 。命名約定如下——如果使用了迭代器或索引集合(例如 Array、NodeList、FileList 等),名稱應(yīng)該是一個復(fù)數(shù)名詞。否則,如果使用了鍵控集合(Set、Map),并且我們只對可以通過鍵獲得的值感興趣(通常使用 Array.from() 或擴展語法),命名約定保持不變——名稱應(yīng)該是一個復(fù)數(shù)名詞。但是,如果鍵對我們也很重要,那么這樣的集合應(yīng)該使用單數(shù)名詞命名,并在名稱末尾添加表示一組某物的前綴之一。例如,Collection、List、Group 等。
類 。在處理類時,遵循幾個約定是很重要的。以下是列表:
常量 。用于描述在程序執(zhí)行之前已知且在執(zhí)行過程中不應(yīng)更改的值。
關(guān)于命名約定,開發(fā)人員之間有一個重要的共識:常量的名稱應(yīng)使用 UPPER_SNAKE_CASE 表示法。
枚舉 。在 JavaScript 中,這種數(shù)據(jù)結(jié)構(gòu)用于枚舉一組固定值。
與許多其他編程語言具有枚舉的單獨數(shù)據(jù)類型不同,JavaScript 沒有這樣的數(shù)據(jù)類型(至少目前沒有)。因此,為了在 JavaScript 中模擬枚舉,可以使用一個普通對象,但需要遵循特定的命名約定。以下是這些命名約定的列表:
由于 TypeScript 現(xiàn)在是 JavaScript 開發(fā)的重要組成部分,值得一提的是 TypeScript 具有用于枚舉的 enum 關(guān)鍵字。如果決定與團(tuán)隊一起使用 TypeScript 的枚舉,慣例是遵循相同的命名約定。
地圖 。也被稱為字典數(shù)據(jù)結(jié)構(gòu)。這種數(shù)據(jù)結(jié)構(gòu)用于將一個值映射到另一個值。
地圖是任何編程語言中非常有用且經(jīng)常使用的數(shù)據(jù)結(jié)構(gòu)。在JavaScript世界中,地圖有特定的命名約定。名稱應(yīng)遵循aToB的模式,其中a作為從地圖中檢索值的鍵,后跟介詞To,暗示著兩個事物的映射,然后是B,它是a的映射值。
// 不好的
const userRolesReadable={
[UserRole.ADMIN]: '管理員',
[UserRole.GUEST]: '訪客',
}
const REDIRECTING={
'/groups': '/admin-login',
'/profile': '/login',
}
const UserPermissions={
[UserRole.ADMIN]: [Permission.MANAGE_USERS, Permission.MANAGE_GROUPS],
[UserRole.GUEST]: [Permission.EDIT_PROFILE],
}
// 好的
const userRoleToReadable={
[UserRole.ADMIN]: '管理員',
[UserRole.GUEST]: '訪客',
}
const pagePathToRedirectPath={
'/groups': '/admin-login',
'/profile': '/login',
}
const userRoleToPermissions={
[UserRole.ADMIN]: [Permission.MANAGE_USERS, Permission.MANAGE_GROUPS],
[UserRole.GUEST]: [Permission.EDIT_PROFILE],
}
JavaScript中有一個內(nèi)置的Map類。與常規(guī)對象的主要區(qū)別在于能夠使用任何數(shù)據(jù)類型(甚至是對象)作為鍵。通常情況下,使用原生的Map類來創(chuàng)建地圖作為數(shù)據(jù)結(jié)構(gòu)是多余的。但是,如果您需要原生Map提供的功能,可以使用它來創(chuàng)建地圖數(shù)據(jù)結(jié)構(gòu)。在大多數(shù)情況下,常規(guī)對象就足夠了。
類型和接口 。如前所述,TypeScript已成為當(dāng)今JavaScript開發(fā)中不可或缺的一部分。一般來說,在大多數(shù)情況下,類型和接口是可以互換的。然而,由于已經(jīng)有足夠的討論關(guān)于選擇哪種,本文將專注于命名。對于類型和接口,存在以下命名約定:
// 不好的
type TUser={
firstName: string
lastName: string
}
interface user {
firstName: string
lastName: string
}
interface userServiceInterface {
findByEmail: (email: string)=> User
}
// 好的
type User={
firstName: string
lastName: string
}
interface User {
firstName: string
lastName: string
}
interface UserServiceContract {
findByEmail: (email: string)=> User
}
// 也可以
interface IUserService {
findByEmail: (email: string)=> User
}
重要的是要意識到,盡管本文對JavaScript命名約定進(jìn)行了廣泛的概述,但它無法涵蓋所有可能的情況。即使在提出的觀點中,也應(yīng)考慮許多例外情況。命名過程雖然基礎(chǔ),但意味著在應(yīng)用中靈活性,考慮到每個項目的獨特特點和要求。
在開發(fā)過程中,我們經(jīng)常深入復(fù)雜的技術(shù)細(xì)節(jié),忘記了力量常常隱藏在細(xì)節(jié)中。多年的開發(fā)經(jīng)驗只能證實這樣一個事實,即對細(xì)節(jié)的關(guān)注,比如命名,對于創(chuàng)建高效和可讀的代碼起著至關(guān)重要的作用。簡潔和無需思考如何命名一個值以及如何快速理解它所包含的內(nèi)容,為開發(fā)人員的日常工作帶來了難以置信的輕松。
如果一個開發(fā)人員的變量沒有被清晰命名,他們能否認(rèn)為自己是強大的?清晰的命名不僅使代碼對其他開發(fā)人員更易理解,也使程序員自己更易理解,從而使開發(fā)過程更高效,減少錯誤。
經(jīng)常發(fā)生的情況是,尋找糟糕的命名會導(dǎo)致發(fā)現(xiàn)糟糕的代碼。這只強調(diào)了命名約定作為代碼質(zhì)量指標(biāo)的重要性。適當(dāng)?shù)拿从沉藢?xì)節(jié)的關(guān)注,進(jìn)而表明了對開發(fā)的細(xì)致態(tài)度。
當(dāng)應(yīng)用本文討論的約定時,從前言部分導(dǎo)入值的方式看起來更清晰了,不是嗎?我相信現(xiàn)在理解每個導(dǎo)入的含義將需要您付出更少的努力。
在結(jié)論中,重要的是要記住,雖然命名標(biāo)準(zhǔn)很重要,但它們并不是絕對的。每個項目都有其特殊性,定義自己的約定至關(guān)重要。最重要的是它們應(yīng)該存在,并且您應(yīng)該遵循它們,以確保代碼的一致性并提高集體生產(chǎn)力。此外,如果可能的話,嘗試將代碼風(fēng)格問題委托給諸如ESLint之類的工具,以簡化和增強開發(fā)過程。
SS命名規(guī)范:
喜歡的給作者點個關(guān)注哦,想要學(xué)習(xí)資料的私聊
TML 符號實體
HTML 符號是不呈現(xiàn)在標(biāo)準(zhǔn)的鍵盤上,比如數(shù)學(xué)運算符、箭頭符號、技術(shù)符號和形狀。
如需向 HTML 頁面添加這些符號,您可以使用 HTML 實體名稱。
如果不存在實體名稱,您可以使用實體編號。
如果字符沒有實體名稱,您可以使用十進(jìn)制(或十六進(jìn)制)引用。
實例
<p>我將顯示 €</p>
<p>我將顯示 €</p>
<p>我將顯示 €</p>
結(jié)果如下:
我將顯示
我將顯示
我將顯示
HTML 支持的數(shù)學(xué)符號
如果您使用的是一個 HTML 實體名稱或一個十六進(jìn)制編號,字符總是能正確顯示。
這是與您頁面使用的字符集相互獨立的!
字符 | 編號 | 實體 | 描述 |
---|---|---|---|
? | ∀ | ∀ | 所有(for all) |
? | ∂ | ∂ | 部分(part) |
? | ∃ | ∃ | 存在(exists) |
? | ∅ | ∅ | 空(empty) |
? | ∇ | ∇ | 倒三角(nabla) |
∈ | ∈ | ∈ | 屬于(isin) |
? | ∉ | ∉ | 不屬于(notin) |
? | ∋ | ∋ | 包含的成員(ni) |
∏ | ∏ | ∏ | 連乘(prod) |
∑ | ∑ | ∑ | 總和(sum) |
完整的數(shù)學(xué)(Math)參考手冊
HTML 支持的希臘字母
字符 | 編號 | 實體 | 描述 |
---|---|---|---|
Α | Α | Α | Alpha(中文注音:阿耳法) |
Β | Β | Β | Beta(中文注音:貝塔) |
Γ | Γ | Γ | Gamma(中文注音:伽馬) |
Δ | Δ | Δ | Delta(中文注音:德耳塔) |
Ε | Ε | Ε | Epsilon(中文注音:艾普西隆) |
Ζ | Ζ | Ζ | Zeta(中文注音:截塔) |
完整的希臘(Greek)參考手冊
HTML 支持的其他實體
字符 | 編號 | 實體 | 描述 |
---|---|---|---|
? | © | © | 版權(quán)所有(REGISTERED SIGN) |
? | ® | ® | 注冊商標(biāo)(REGISTERED SIGN) |
| € | € | 歐元符號(EURO SIGN) |
? | ™ | ™ | 商標(biāo)(trademark) |
← | ← | ← | 向左箭頭(LEFTWARDS ARROW) |
↑ | ↑ | ↑ | 向上箭頭(UPWARDS ARROW) |
→ | → | → | 向右箭頭(RIGHTWARDS ARROW) |
↓ | ↓ | ↓ | 向下箭頭(DOWNWARDS ARROW) |
? | ♠ | ♠ | 黑桃(BLACK SPADE SUIT) |
? | ♣ | ♣ | 黑梅花(BLACK CLUB SUIT) |
? | ♥ | ♥ | 黑心(BLACK HEART SUIT) |
? | ♦ | ♦ | 黑方塊(BLACK DIAMOND SUIT) |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。