前端開發變量命名系列 - JavaScript篇

JavaScript做爲前端開發從業人員必須掌握的3大基礎知識中最重要的一環,也是平是接觸時間最長、寫得最多的。在開發過程當中必然會遇到命名的問題,你會詞窮、糾結、惆悵嗎?本文的出現相信可以解決大部分煩惱,讓你輕鬆寫出符合規範、易讀、簡短的代碼。javascript

本文將經過大量的實例來試圖自圓其說,造成一套系統化、實用的變量命名理化體系。經過按JavaScript的數據類型分類着手、細到一個函數的參數命名,並提供衆多可選方案,並儘可能給出其適用範圍和利弊。html

須要注意的是因爲我的寫做水平、和知識有限,不少方面敘述上有些生硬,在分類上也沒有什麼特別的依據,文章也沒有人審稿,因此有什麼紕漏還請留言告知。因爲寫做倉促,內容可能不全,後續會隨着工做和學習的深刻而不斷地調整和更新。

布爾值(Boolean)命名

Boolean值是兩種邏輯狀態的變量,它包含兩個值:。在JavaScript中對應 truefalse,在實踐中一般使用數字1表示真值,0來表示假值。前端

雖然Boolean的狀態只有兩種可是在命名時能夠進一步分類,這裏給出幾種場景:vue

場景一:表示可見性、進行中的狀態

解釋可見性在一般指頁面中的元素、組件是否顯示(或者組件掛載到DOM上,但並不可見)。進行中主要是說明某種狀態是處於持續進行中。java

推薦命名方式爲 is + 動詞(如今進行時)/形容詞,同時這種方式也能夠直接不寫 is,可是爲了更好的做區分,建議仍是加上。node

{
  isShow: '是否顯示',
  isVisible: '是否可見',
  isLoading: '是否處於加載中',
  isConnecting: '是否處於鏈接中',
  isValidating: '正在驗證中',
  isRunning: '正在運行中',
  isListening: '正在監聽中'
}
注意: 在Java中使用這種方式是有必定反作用的,爲何請移步: 爲何阿里巴巴禁止開發人員使用 「isSuccess」 做爲變量名?

場景二:屬性狀態類

解釋:一般用來描述實體(例如:HTML標籤、組件、對象)的功能屬性,並且定法比較固定。react

{
  disabled: '是否禁用',
  editable: '是否可編輯',
  clearable: '是否可清除',
  readonly: '只讀',
  expandable: '是否可展開',
  checked: '是否選中',
  enumberable: '是否可枚舉',
  iterable: '是否可迭代',
  clickable: '是否可點擊',
  draggable: '是否可拖拽'
}

場景三:配置類、選項類

解釋:主要是指組件功能的開啓與關閉,功能屬性的配置。git

這是一種比較常見的情景,目前命名方式也有不少種,可是概括起來也很少。推薦使用 withXx 來表示組件在基本功能形態外的其它功能,好比組件的基礎功能到高級功能的開啓;使用 enableXx 來表示組件某些功能的開啓;使用 allowXx 來表示功能屬性的配置;使用 noXx 用於建議功能使用者這個不建議開啓。github

{
  withTab: '是否帶選項卡',
  withoutTab: '不帶選項卡',
  enableFilter: '開啓過濾',
  allownCustomScale: '容許自定義縮放',
  shouldClear: '是否清除',
  canSelectItem: '是否能選中元素',
  noColon: '不顯示label後面的冒號',
  checkJs: '檢查Js',
  emitBOM: 'Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.'
}
注意:若是嫌分類太多,能夠只使用其中一種方式,好比在Typescript中使用了 allownXxnoXx

除了上面這些帶有特定的前置介詞、動詞方式外還有一些在語義上帶有疑問性質的組合一般也是做爲Boolean命名的一種參考。vue-router

{
  virtualScroll: '是否啓用虛擬滾動模式',
  unlinkPanels: '在範圍選擇器裏取消兩個日期面板之間的聯動',
  validateEvent: '輸入時是否觸發表單的校驗'
}

函數命名

函數在不一樣的上下文中的叫法也不同,在對象中稱爲方法,在類中有構造函數、在異步處理時有回調函數,還有當即執行函數、箭頭函數、柯里函數等。

函數命名的方式經常是和業務邏輯耦合在一塊兒的,可是在命名規則上也有一些常見的模式能夠遵循。

場景一:事件處理

事件處理函數是前端平時用到最多的,包括瀏覽器原生事件、異步事件和組件自定義事件。在寫法上最多見的兩種命名分別爲 onXxonXxClickhandleXxhandleXxChange

這裏如何在兩者之間選擇,能夠從二方面來歸類。一是,原生事件採用 onXx,而自定義事件使用 handleXx。二是,事件主動監聽採用 onXx,被動處理使用 handleXx

從實踐及三大主流框架的文檔關於事件部分的內容來看,推薦使用 handleXx 這種方式,而在表單提交的時候一般採用 onSubmit 函數。

其實,在實際項目中不多嚴格這樣來命名事件處理函數,由於這種方式有必定的侷限性,好比點擊按鈕打開一個對話框,使用 handleOpenDlgonOpenDlg 都沒有直接寫 openDlg 方便,若是頁面有多個不一樣功能的對話框採用這種方式會顯得變量名過長,而handle和on就顯得沒有必要了,好比 hanldeOpenCommentDlg 就沒有 openCommentDlg 直白。

下面列出了一些約定成俗的適用例子:

{
  onSubmit: '提交表單',
  handleSizeChange: '處理分頁頁數改變',
  handlePageChange: '處理分頁每頁大小改變',
  onKeydown: '按下鍵'
}

場景二:異步處理

這裏主要是指在寫數據層服務、狀態管理中的Action命名,以及Ajax回調的命名規則。

{
  getUsers: '獲取用戶列表',
  fetchToken: '取得Token',
  deleteUser: '刪除用戶',
  removeTag: '移除標籤',
  updateUsrInfo: '更新用戶信息',
  addUsr: '添加用戶',
  createAccount: '建立帳戶'
}

命名主要圍繞數據的增刪查找來劃分,獲取數據一般是 getXxfetchXx,在做者看來二者在使用上的區分在於 getXx 的數據來源不必定直接取自異步的原始數據,多是加工處理後的,而 fetchXx 是直接拿的原始數據。固然在實際項目中並無區分,看我的喜愛。

deleteXx 主要用於數據刪除,而 removeXx 在語義上是移除數據,一般狀況數據是還存在的,只是沒有顯示或數據假刪除。updateXx 是指數據更新操做,addXx 是在已有列表數據中添加新的子項、而createXx 主要是建立新的實例,好比新建一個帳戶。

場景三: 跳轉路由

在實際開發過種中,好比在使用react-router/vue-router時,在模板或者JSX中能夠直接在標籤中寫上目標地址,但有些時候跳轉的目標地址是通過判斷或者組合後的,而且經過事件觸發跳轉的,這個時候就須要一個函數來處理,那麼在函數命名的時候能夠考慮使用

{
  toTplDetail: '跳轉到模板詳情頁面',
  navigateToHome: '導航到首頁',
  jumpHome: '跳轉首頁',
  goHome: '跳轉首頁',
  redirectToLogin: '重定向到登陸頁',
  switchTab: '切換Tab選項卡',
  backHome: '回到主頁'
}

推薦使用 toXxgoXx 這兩種方式,若是不是在當前頁面打開/跳轉頁面,可使用 toBlankTplDetail 或者 goBlankHome 這種方式來進一步語義化。若是前端頁面是位於Webview中,也能夠考慮採用 toNativeShare 這種方式來命名。

場景四:框架相關特定方法

這裏主要是針對前端3大主流流行框架,有一些命名是帶有特定標識符的,還有就是一些生命週期的命名方式。

{
  formatTimeFilter: '在AngularJs和Vue中,一般用於過濾器命名',
  storeCtrl: '用於AngularJs定義控制器方法',
  formatPipe: '用於Angular中,標識管道方法',
  $emit: 'Vue中的實例方法',
  $$formatters: 'AngularJs中的內置方法',
  beforeCreate: 'Vue的生命週期命名',
  componentWillMount: 'React生命週期命名',
  componentDidMount: 'React生命週期命名',
  afterContentInit: 'Anuglar生命週期命名',
  afterViewChecked: 'Angula生命週期命名',
  httpProvider: 'AngularJs服務',
  userFactory: '工廠函數',
  useCallback: 'React鉤子函數'
}

場景五:數據的加工

這類場景在處理列表的時候常常會碰到,好比排序、過濾、添加額外的字段、根據ID和索引獲取特定數據等。

情形一:根據特定屬性獲取屬性

這裏能夠參考DOM方法的命名,好比:getElememtById()getElementsByTagName()getElementsByClassName()getElementsByName(),而後提煉出一個比較實用的模板:getXxByYy()。其中 Xx 能夠是:element, item, option, data, selection, list, options 以及一些特定上下文的名字,好比:user(s), menu(s) 等。Yy 相對來講比較固定,常常用到的就是 id, index, key, value, selected, actived 等。

除了使用 get,還可使用 queryfetch,可是須要注意和上面提到的異步數據處理做一個區分。

{
  getItemById: '根據ID獲取數據元素',
  getItemsBySelected: '根據傳入的已選列表ID來獲取列表所有數據',
  queryUserByUid: '根據UID查詢用戶'
}

注意:在 getItemsBySelected 這種情形下直接寫成 getItemsSelected 更好,但只適用於 Yy 爲形容詞的場景

情形二:格式化數據

這裏的格式化操做包括排序、調整數據結構、過濾數據、添加屬性。命名一般使用 formatXx, convertXx, inverseXx, toggleXx, parseXx, flatXx, 也能夠結合數組的一些操做方法來命名,好比 sliceXx, substrXx, spliceXx, sortXx, joinXx 等來命名。

{
  formatDate: '格式化日期',
  convertCurrency: '轉換貨幣單位',
  inverseList: '反轉數據列表',
  toggleAllSelected: '切換全部已選擇數據狀態',
  parseXml: '解析XML數據',
  flatSelect: '展開選擇數據',
  sortByDesc: '按降序排序'
}

數組命名

數組的命名推薦使用複數形式來命名,還有就是名詞和具備列表意思的單詞組合。常見的詞彙有 options, list, maps, nodes, entities, collection 等。

{
  users: '用戶列表',
  userList: '用戶列表',
  tabOptions: '選項卡選項',
  stateMaps: '狀態映射表',
  selectedNodes: '選中的節點',
  btnGroup: '按鈕組',
  userEntities: '用戶實體'
}

選項元素、下拉元素命名

主要針對的是在下拉選擇框、選項卡元素、Radio、Checkbox等數據源每一個選項數據的命名。常見的詞彙有:title, name, key, label, field, value, id, children, index, nodes 等。

基中 title/name/key/label/field 做爲選項顯示名, value/id 用於惟一標識選項,children/nodes 用於包含子節點內容。若是選項元素的語義很明確的狀況下也能夠直接使用特定單詞來代替提到的這些泛指的詞彙,例如菜單列表就可使用 menu 來做爲顯示名。

// 最多見組合
{
  title: '標題',
  value: 'ID值'
}

// 組合二
{
  label: '標籤名',
  value: 'ID值'
}

// 組合三
{
  name: '元素名',
  id: 'ID值'
}

// 組合四
{
  field: '字段',
  value: '標識',
  index: '索引'
}

當前選項、激活項命名

適用列表的選中項、菜單選中項、步驟操做的當前進行步驟、頁面路由當前路由等的命名。

{
  activeTab: '當前選中選項卡',
  currentPage: '當前頁',
  selectedData: '當前選項中數據',
}

臨時數據、比對數據命名

針對在代碼中有時會使用一些臨時的變量來存儲數據、保存數據快照的場景下的命名。

{
  swapData: '臨時交換數據',
  tempData: '臨時數據',
  dataSnapshot: '數據快照'
}

數據循環語句中變量命名

在使用 for 循環時,多層嵌套請依次使用 i/j/k,超過3層可使用 x/y/zm/n 來命名。使用 forEach, map, filter 等方法時,每個元素命名能夠根據不一樣語境下的特殊名字來命名,好比遍歷 menus,那麼每一個元素能夠命名爲 menu,否則則使用上下文無關的詞彙,好比:item, option, data, key, object 等。至於索引一般使用 index,若是多層可使用 index + 數字 的形式,也能夠直接使用 i/j/k 來做爲索引,甚至還可使用 subIndex/grandIndex 這種方式來命名。

對於在使用 for 循環時數組長度若是須要單獨命名的話,可使用 xxlength/xxLens,或者 xxCount

在循環的過程當中一般還會統計某個條件下數據匹配的次數、重複元素數量、記錄中間結果等狀況。這裏推薦使用 count 表示次數,skipped 表示跳過的數量,result 表示結果。

// for 循環
for (let i = 0; i < 10; i++) {
  for (let j = 0; j < 10; j++) {
    for (let k = 0; k < 10; k++) {
      // do something
    }
  }
}

for (let i = 0, lens = this.options.length; i < lens; i++) {
  // do something
}

// forEach
users.forEach((item, index) => {
  // do something
})

menus.forEach((menu, index) => {
  if (menu.children) {
    menu.children.forEach((subMenu, subIndex) => {
      if (subMenu.children) {
        subMenu.children.forEach((grandMenu, grandIndex) => {
          // 一個不經常使用的示例
        })
      }
    })
  }
})

方法參數命名

方法的參數名稱和數量在不一樣的方法中各不相同,可是仍是有一些固定的模式能夠參考,好比在Vue中監聽屬性變化的新值和舊值;reduce 方法的上一個值,當前值;回調函數的命名、剩餘參數的命名等。

情形一:新值、舊值

常見於Vue中watch 對像中的屬性監聽回調函數,推薦使用

{
  oldVal: '舊值',
  newVal: '新值'
}

情形二:上一個值、下一個值和當前值

這種情形見於路由的鉤子方法,Object.assign 數據拷貝的參數。

// 組合一
{
  from: '從...',
  to: '到...'
}

// 組合二
{
  prev: '上一個...',
  next: '下一個...',
  cur: '當前'
}

// 組合三
{
  source: '源',
  target: '目標'
}

// 組合四
{
  start: '開始',
  end: '結束'
}

情形三:異步數據返回

用於Promise的then方法參數,await 的返回的Promise等。可選擇的詞彙有:res, data, json, entity,推薦使用 res

demoPromise.then(res => {
  // do something
})

情形四:其它狀況

一些使用很少,可是在編程時約定成俗的命名方式。例如 ch 表示單個字符,str 表示字符串, n 表明次數, reg 表示正則, expr 表示表達式, lens 表示數組長度, count 表示數量, p 表示數據的精度, q 表示查詢(query), src 表示數據源(source), no 表示數字(number), rate 表示比率, status 表示狀態, bool 表示布爾值, arr 表示數組值, obj 表示對象值, xy 表示座標兩軸, func 表示函數, ua表示User Agent, size 表示大小, unit 表示單位, hoz 表示水平方向, vert 表示垂直方向, radix 表示基數,根

// 傳入單個字符
function upper(ch) {}

// 數量重複
function repeat(str, n)

// 正則
'abab'.replace(reg, 'bb')

事件命名

這裏根據DOM、nodejs和一些框架和UI組件的事件進行概括

DOM事件

這裏列舉DOM中常見的事件命名

{
  load: '已完成加載',
  unload: '資源正在被卸載',
  beforeunload: '資源即將被卸載',
  error: '失敗時',
  abort: '停止時',
  focus: '元素得到焦點',
  blur: '元素失去焦點',
  cut: '已經剪貼選中的文本內容而且複製到了剪貼板',
  copy: '已經把選中的文本內容複製到了剪貼板',
  paste: '從剪貼板複製的文本內容被粘貼',
  resize: '元素重置大小',
  scroll: '滾動事件',
  reset: '重置',
  submit: '表單提交',
  online: '在線',
  offline: '離線',
  open: '打開',
  close: '關閉',
  connect: '鏈接',
  start: '開始',
  end: '結束',
  print: '打印',
  afterprint: '打印機關閉時觸發',
  click: '點擊',
  dblclick: '雙擊',
  change: '變更',
  select: '文本被選中被選中',
  keydown/keypress/keyup: '按鍵事件',
  mousemove/mousedown/mouseup/mouseleave/mouseout: '鼠標事件',
  touch: '輕按',
  contextmenu: '右鍵點擊 (右鍵菜單顯示前)',
  wheel: '滾輪向任意方向滾動',
  pointer: '指針事件',
  drag/dragstart/dragend/dragenter/dragover/dragleave: '拖放事件',
  drop: '元素在有效釋放目標區上釋放',
  play: '播放',
  pause: '暫停',
  suspend: '掛起',
  complete: '完成',
  seek: '搜索',
  install: '安裝',
  progress: '進行',
  broadcast: '廣播',
  input: '輸入',
  message: '消息',
  valid: '有效',
  zoom: '放大',
  rotate: '旋轉',
  scale: '縮放',
  upgrade: '更新',
  ready: '準備好',
  active: '激活'
}

自定義事件

在封裝組件時提供的事件名除了參考DOM事件外,在命名上也能夠參考Github Api 採用 動詞過去時 + Event 的方式, Visual Studio Code Api的 `on +

{
  assignedEvent: '分配事件',
  closedEvent: '關閉事件',
  labeledEvent: '標籤事件',
  lockedEvent: '鎖事件',
  deployedEvent: '部署事件'
}

此外,不少命名方式能夠根據場景使用 元素 + click元素 + changeselect + 範圍等方式靈活運用

{
  selectAll: '選擇全部',
  cellClick: '當某個單元格被點擊時會觸發該事件',
  sortChange: '當表格的排序條件發生變化的時候會觸發該事件'
}

狀態管理命名

若是在項目中用到了狀態管理(redux/vuex/ngrx),下面給出一些ActionType,Mutation, Action的命名參考。

// Redux 的 actionType
LOAD_SUCCESS
LOAD_FAIL
TOGGLE_SHOW_HISTORY
ON_PLAY
ON_LOAD_START
FETCH_SONGS_REQUEST
RECEIVE_PRODUCTS

// ngrx
const SET_CURRENT_USER = '[User] Set current';
const ADD_THREAD = '[Thread] Add';
const UPDATE_TRIP_SUCCESS = 'Update [Trip] Success';

其它命名

// 日期、時間
// --------------------------------------------------------
sentAt: '發送時間'
addAt: '添加時間'
updateAt: '更新時間'
startDate: '開始日期'
endDate: '結束日期'
startTime: '開時時間'
endTime: '結束時間'

參考

文章的寫做過程當中參考大量優秀的文章、優秀開源項目的源碼、流行框架的最佳實踐指南以及一些SDK的接口文檔。

相關文章
相關標籤/搜索