[TOC]
## 前言
本文開始針對項目中總結出來的關于js基礎知識的代碼優化技巧進行每個細節點的分析,后續還會針對某個專題的分析。
## 案例說明
### if針對同一關鍵值多條件的判斷
針對key進行多條件判斷,而其中的多條件可能有些可以歸為一類,因為其執行的代碼是相同的
```
//優化前
if(key === 1 || key ===3 || key===9){
//some codes here
}
//優化后
let codesOptionArr = [1,3,9]
if(codesOptionArr.includes(key)){
//some codes here
}
```
### 針對多case,分別返回或者設置不同值,代碼段很簡單
需要根據不同的值情況,來返回或者設定對應的值,相信很多人會說用switch來進行優化,其實用對象字面量會更好,也更方便維護和復用。比較常見的是前端常見的一些枚舉數據以及固定值。
```
//優化前
let str =''
switch(type){
case 'name': str ='姓名'
break
case 'sex': str ='性別'
break
}
//優化后
function getTypeStr (type){
if(!type) return ''
let dict = {
name:'姓名',
sex:'性別'
}
return dict[type] || type
}
let str = getTypeStr(type)
```
### 少寫嵌套,盡早返回
缺點除了邏輯分不清楚,還會導致代碼執行性能低,在執行完需要的邏輯之后不能跳出方法。所以建議針對已經符合返回的情況下 ,就返回對應的邏輯,不再進行多余的判斷。
```
//優化前
function judgeAge(age){
let str =''
if(age && !isNaN(age) && age> 0 ){
if(age <18) {
str = '還是未成年 '
} else {
str = '符合要求'
}
} else {
str = '年齡不合法'
}
return str
}
//優化后
function judgeAge(age){
if(!age || isNaN(age) || age < 0 ){
return '年齡不合法'
}
if(age<18) return '還是未成年'
else{
return '符合要求'
}
}
```
### 方法內的返回或者對應關系具有關聯關系,或者可以進行一定的代碼關聯設計,這里不針對對象字面量。
```
//優化前
let str =''
switch(number) {
case 0 : str = '沒有任何收入'
break
case 1 :str='您有一枚硬幣了'
break
}
return str
//優化后
let descArr = ['沒有任何收入','您有一枚硬幣了']
return descArr[number]
```
### 使用函數默認值和解構
也許你之前沒有用過函數默認值,也沒有分析過解構能帶來什么優化。
```
// 優化前
function fn(age){
let _age = age || 0
console.log(_age)
}
// 優化后
function fn(age = 0){
console.log(age)
}
// 優化前
function fn(person){
if(person && person.name) {
console.log(pserson.name || '')
}
}
// 優化后
function fn({name}){
console.log(name || '')
}
```
### 合并條件與執行語句
在庫代碼中經常看到一些判斷條件與執行語句、返回語句寫在一起,非常簡潔高效,也可讀性較高。
```
let getArrlen= (str,arr) => {
if(!(arr instanceof(Array))) return 'arr is not arr '
return arr && arr.length
}
```
### 批量對象屬性賦值
使用場景:主要是針對需要把對象的一些屬性批量的賦值到另外一個對象上,然后如果你的屬性很多可能要寫很多賦值語句。(前提是屬性名一般是相同的)
> 說明:可能有人會問為什么不直接用這個對象,答案也很簡單,如果可以直接用,當然直接用是最好的,我自己在寫接口param的時候,就會注意這些,需要傳參的部分封裝到一個特殊的對象里,然后進行data的綁定,這樣需要的時候直接用傳參對象。但這里討論的不是這種情況。
```
//優化前
let data = {}
data.name = this.form.name
data.len = this.form.len
data.amount = this.form.amount
//優化版本一 :利用對象的解構
let {name,len,amount} = this.form
//利用對象解構還可以支持屬性名變更的情況
let {name,len:length,amount:money} = this.form
let data = {name,len,amount}
// 優化后
let data = this.setProps[{source:this.form,propArr:['name','len','amount']}]
//優化版本二 :可以支持批量的導入需要賦值的,對于拷貝對象,用source屬性承接,而需要賦值的屬性用propArr承接
//在方法中用json的相關方法支持了簡單的對象深拷貝
// 批量加載對象屬性,支持傳入數組[{source:sourceObj,propArr:[]}]
setProps(arr) {
if (arr.length <= 0) return {}
return arr.reduce((acc, item) => {
item.propArr.reduce((acc, prop) => {
if (typeof item.source[prop] === 'object') {
acc[prop] = JSON.parse(JSON.stringify(item.source[prop]))
} else {
acc[prop] = item.source[prop]
}
return acc
}, acc)
return acc
}, {})
}
```
**拓展思考**:像這種代碼如果你的vue代碼里經常寫,不妨在你的mixins中混入這個方法,可以為你的頁面節省大量的代碼空間。
### 批量變量重置
在我們的代碼中經常會遇到吧一些變量進行重置,這部分代碼重復率很高又沒有技術含量,所以我寫一個工具方法進行簡單的支持,代碼優化。
```
//優化前
this.search = false
this.data = []
this.cur_page = 1
this.pageNo = 1
this.totalCount = 0
this.processType = ''
this.person = ''
this.keyword = ''
this.taskStatus = ''
this.stdate = []
this.processStatus = ''
// 優化后
this.resetVars([this.data,this.processType,this.person,this.keyword,this.taskStatus])
/**
* @author zhangbing
* @param [] arr 需要重置的數組變量
* @param {*} options 配置對象 對于這里的重置規則如果不符合需求的可以自定義option字典,然后用instanceof 判斷類型(todo)
*/
resetVars(arr, options) {
if (!arr || arr.length === 0) return
let _options = {
object: {},
string: '',
number: 0,
boolean: true,
null: null,
undefined: undefined
}
_options = options ? Object.assign({}, _options, options) : _options
return arr.map(item => {
if (_options.includes(typeof item)) {
item = _options[typeof item]
} else {
// 不存在重置類型的 重置為字符串
item = ''
}
return item
})
}
```
**拓展思考**:像這種代碼如果你的vue代碼里經常寫,不妨在你的mixins中混入這個方法,可以為你的頁面節省大量的代碼空間。
### 對象的淺拷貝與深拷貝
在js中,我們可以用等號來進行基本數據類型的賦值,而對于復雜數據類型也就是對象類型,其等號賦予的是對象地址,不能實現拷貝的目的。而我們知道的Object.assign實現的也是對象的淺拷貝。
所以一般情況下,如果你不確定的情況下,如果發現對象屬性值是對象類型,需要遞歸拷貝。核心知識點是:typeof source[prop] === 'object' ,return Object.assign(target[prop],source[prop]),直到對象屬性為基本類型.
這里所講的不是這部分,而是利用JSON的轉化方法來實現簡單的對象深拷貝。當然這種方法是有弊端的,詳情參考我另一篇文章利用json序列化對象的問題
```
let target = JSON.parse(JSON.stringify(source))
```
## 更多
以上方法只是根據個人經驗和想法進行的一些可優化的思維拓展,有些可能是矯枉過正,但代碼的優化道路上,從來都是要特定場景下解決特定需求的,為的還是要讓使用更簡單,讓使用者更習慣、高效的開發,提前或者滯后的將代碼進行優化重構固然都是錯的,但如果一點點優化的思考和什么程度應該去做重構了不去探索就進步太慢了。
## 其他文章推薦
- [匿名函數重構代碼](https://mp.weixin.qq.com/s/zan0akmtbn_5FXqY_Qy4hQ)
- 前端入門
- 前端入職須知
- 入職準備
- 前端ide
- vsc快速上手指南
- 上手指南一
- 常用插件推薦
- 微信開發者
- sublime的使用
- hbuilder入門
- ws
- 前端面試
- 概要
- bat面試題庫
- 題庫一
- 面試大綱
- 題庫二
- 面試大綱
- 前端基礎面試題
- js基礎面試題
- vue&&react面試題
- 數據結構&&算法面試題
- 題庫三
- 001
- 題庫四
- 中小公司leader
- 常規題庫
- 前端規范
- 001
- css
- 001
- 002
- es6(js)
- 001
- 002
- 003
- 004
- node
- 001
- vue
- 001
- react
- 001
- 預處理器
- 001
- gulp
- 001
- webpack
- 001
- 設計模式
- 001
- web常識
- 001
- koa
- 001
- 小程序
- 001
- 數據結構與算法
- 001
- 推薦文章
- 面試指南
- web性能
- 面試分享
- 001
- ps
- ps入門階段
- 圖片類型以及區別
- 基本概念以及常用工具
- ps操作技巧
- 幾個問題
- ps互動教程軟件(app)
- 資源導航
- ps站點資源導航
- ui站點導航
- html
- h5專題
- audio/video
- Geolocation
- Websockets
- Web storage
- Communication
- Web Workers
- requestAnimationFrame
- async&&defer
- fileApi
- h5調用底層能力
- input新解
- canvas實戰篇
- 教程
- js
- javascript入門
- js代碼審查工具
- js性能優化
- 瀏覽器dom對象
- js優質資源
- indexDB入門
- jquery
- jq基本語法
- jq插件與原生插件
- Jq使用建議
- ajax后退解決方案
- jq常見問題
- js常用技術
- js控制運動-move.js
- 常用正則歸納
- js實用技術
- 鼠標行為分析
- document.referrer
- 你可能不知道的調試技巧
- 表格文件的讀取與下載
- 異步編程那些事
- 數據結構
- 編程環境和模型
- 列表
- 棧
- 隊列
- 鏈表
- 字典
- 散列
- 集合
- 二叉樹和二叉查找樹
- 參考
- js編程
- js模塊機制
- 算法
- 基本算法
- 遞歸
- 圖和圖算法
- 圖定義
- 系統建模
- 圖類
- 搜索圖
- 查找最短路徑
- 拓撲排序
- 圖實踐
- 排序算法
- 測試平臺
- 冒泡排序
- 選擇排序
- 插入排序
- 基本排序的比較
- 希爾排序
- 歸并排序
- 快速排序
- 實踐
- 二分排序
- 檢索算法
- 順序查找
- 二分查找
- 查找文本數據
- 檢索實踐
- 高級算法
- 動態規劃
- 貪心算法
- 高級算法實踐
- 代碼重構
- 簡化函數參數
- 001
- 002
- 基礎鞏固
- 001
- es2015實戰
- 初識es-module
- 異步編程
- es6工廠函數
- filter|map|reduce
- js實戰篇
- 前端圖像處理
- touch事件知多少
- 手勢與實踐
- print表格分頁
- 精彩文章推薦
- 001
- 插件庫
- 插件大全
- 功能性插件
- pdfjs
- wdatepicker
- qrcoder
- barcode插件
- photoviewer
- hammer.js
- echarts
- 視頻控件
- 發送瀏覽器通知
- 觸屏簽名插件
- 圖片相關插件推薦
- 待分類插件(pc)
- 待分類插件(手機端)
- 交互組件
- layerjs
- web
- web兼容
- pc端兼容bug匯總
- ie兼容bug匯總
- ie8測試專題
- web常用技術點
- web兼容匯總001
- ie6專題
- css兼容
- web安全
- web安全初級
- app/h5組件
- app教程
- 前端教程
- rubikx的教程
- 與app交互邏輯
- h5喚起app通識
- webview專題
- webview總綱
- js與oc交互協議
- js與安卓交互協議
- 兼容問題匯總
- jsBridge專題
- errorBook.js
- 常用工具
- chrome-devtool使用
- chraels
- 開發注意事項
- web常識
- markdown教程
- 自定義風格思路
- 經驗與問題總結
- 總結1
- 前端應該注意哪些seo
- 懶加載和預加載
- https
- 前端重構
- web優化
- 移動端web優化
- http緩存
- web端優化
- 圖片專題
- svg專題
- 深入淺出svg
- 地圖使用
- 注意事項
- 需求提交
- 常規交互需求提交
- 緩存
- 干貨文章
- 瀏覽器緩存
- 內存
- web性能指南
- 讀書筆記
- ui框架
- 概論
- easyui
- bootstrap
- 入門推薦
- modal插件使用
- 按鈕組件
- 正確使用柵格布局
- 下拉框插件使用
- 表單使用與驗證
- tab切換項插件
- 分頁控件
- 進度條控件
- 文件上傳控件
- 面板控件
- 常見特效與插件
- weui
- sui-pc
- sui-mobile
- layerUI
- frozen-UI
- rubik-u那些事
- 基本內容
- 小程序
- 小程序入門
- 入門
- 實踐踩坑
- 001
- 基本語法
- 開發大綱
- 注意事項
- 微信專題
- 基本入門
- 準備工作
- 定制菜單
- 圖文消息與圖文推送
- h5支付
- 公眾號支付
- node完成微信支付
- 進階使用
- 微信分享
- weui使用
- 基本使用
- 支付寶專題
- 支付寶h5支付
- app支付接入
- 服務窗支付
- java
- java入門
- eclipse基本使用
- 語言特點
- java代碼規范
- 編譯調試
- java基本語句
- springMVC
- javaweb
- vm模板引擎
- freemarker
- 常用常識
- 常用常識2
- 部署項目
- web --xml文件解析
- java生成pdf文件
- java讀取、寫文件案例
- 圖片加水印
- 圖片加水印2
- java-cookie
- 驗證碼文件
- sql-mapper語法
- maven教程
- mySql教程
- jeecms
- flash
- flash入門
- flash準備工作
- 運行與編譯
- 瀏覽器中flash設置教程
- flash檢測