上篇文章寫了添加擴展性方面的重構,講到了開放封閉原則。學習的步伐不能就此中止,今天的文章,將會說起開發的另外一個原則:單一職責原則。通俗點說就是一個函數只作一件事,下面將會經過幾個實例,探究單一職責原則。css
單一職責的定義能夠理解爲:一個對象或者方法,只作一件事。html
遵照單一職責的實例太多了,下面簡單列舉一下。數組
原生的API方面瀏覽器
trimRight()和trimLeft():trimRight 只負責去除右邊的空白,其它地方一律無論。 trimLeft 只負責去除右邊的空白,其它地方也一律不關。bash
concat(): concat 只負責鏈接兩個或更多的數組,並返回結果。不會涉及刪除數組的操做。微信
toFixed(): toFixed 只把 Number 類型的值四捨五入爲指定小數位數的數字。不會執行其它操做。函數
JQuery 的 API學習
$.each() 只負責遍歷,要處理什麼,本身再動手操做。動畫
css() 只負責設置 DOM 的 style ,不會設置 innerHTML 。this
animate() 只負責執行 CSS 屬性集的自定義動畫,不會涉及其它操做。
說是這樣說,可是你們看着可能會有點懵,看不出來遵照單一原則有什麼好處,下面看一個實例。
以下例子:
現有一批的錄入學生信息,可是數據有重複,須要把數據根據 id 進行去重。而後把爲空的信息,改爲'--'。
let students=[ { id:5, name:'守候', sex:'男', age:'', }, { id:2, name:'浪跡天涯', sex:'男', age:'' }, { id:5, name:'守候', sex:'', age:'' }, { id:3, name:'鴻雁', sex:'', age:'20' } ]; function handle(arr) { //數組去重 let _arr=[],_arrIds=[]; for(let i=0;i<arr.length;i++){ if(_arrIds.indexOf(arr[i].id)===-1){ _arrIds.push(arr[i].id); _arr.push(arr[i]); } } //遍歷替換 _arr.map(item=>{ for(let key in item){ if(item[key]===''){ item[key]='--'; } } }); return _arr; } console.log(handle(students))
運行結果沒有問題,可是你們想一下,
1.若是改了需求,好比,學生信息不會再有重複的記錄,要求把去重的函數去掉,不管,就是整個函數都要改了,還影響到下面的操做。
2.若是項目另外一個地方也是一樣的操做,可是不須要去重。這樣只能再寫一個基本同樣的函數,由於上面的函數沒法複用。以下
function handle1(arr) { //數組深拷貝 let _arr=JSON.parse(JSON.stringify(arr)); //遍歷替換 _arr.map(item=>{ for(let key in item){ if(item[key]===''){ item[key]='--'; } } }); return _arr; }
3.若是項目有一個地方還須要根據 ID 排序。這樣仍是得寫一個函數,由於在不能在上面的函數上面排序。
function handle2(arr) { //數組去重 let _arr=[],_arrIds=[]; for(let i=0;i<arr.length;i++){ if(_arrIds.indexOf(arr[i].id)===-1){ _arrIds.push(arr[i].id); _arr.push(arr[i]); } } //遍歷替換 _arr.map(item=>{ for(let key in item){ if(item[key]===''){ item[key]='--'; } } }); //根據ID排序 _arr.sort((item1,item2)=>item1.id-item2.id); return _arr; }
這樣的問題就是在於,面對需求的變化,不能靈活的處理。函數也基本沒辦法複用。
下面使用單一原則構造一下
let handle={ //數組去重 removeRepeat(arr){ let _arr=[],_arrIds=[]; for(let i=0;i<arr.length;i++){ if(_arrIds.indexOf(arr[i].id)===-1){ _arrIds.push(arr[i].id); _arr.push(arr[i]); } } return _arr; }, //遍歷替換 setInfo(arr){ arr.map(item=>{ for(let key in item){ if(item[key]===''){ item[key]='--'; } } }); return arr; }, //根據id排序 sortForId(arr){ return arr.sort((item1,item2)=>item1.id-item2.id); } }; //去重 students=handle.removeRepeat(students); //設置信息 students=handle.setInfo(students); console.log(students);
結果同樣,並且這樣的方式,可使得方法能夠組合使用,更加的靈活,也方便複用。
若是還須要根據ID排序,就在上面代碼執行結果的基礎上,再加一行代碼便可。
//根據ID排序 students=handle.sortForId(students); console.log(students);
若是原始數據不須要去重,設置完信息以後,直接排序
let students=[ { id:5, name:'守候', sex:'男', age:'', }, { id:2, name:'浪跡天涯', sex:'男', age:'' }, { id:5, name:'守候', sex:'', age:'' }, { id:3, name:'鴻雁', sex:'', age:'20' } ]; //設置信息 students=handle.setInfo(students); //根據ID排序 students=handle.sortForId(students);
這樣操做起來,即便之後需求有改動,在可控的範圍內,能夠靈活的組合使用,函數也能夠複用。
若是以爲要讓 students 連續賦值麻煩,能夠借鑑 JQuery 的鏈式調用方式。
let ec=(function () { let handle=function (obj) { this.obj=JSON.parse(JSON.stringify(obj)); }; handle.prototype={ /** * @description 去重 */ unique(){ //根據id數組去重 let _arr=[],_arrIds=[]; for(let i=0;i<this.obj.length;i++){ if(_arrIds.indexOf(this.obj[i].id)===-1){ _arrIds.push(this.obj[i].id); _arr.push(this.obj[i]); } } this.obj=_arr; return this; }, /** * @description 設置保密信息 */ setInfo(){ this.obj.map(item=>{ for(let key in item){ if(item[key]===''){ item[key]='--'; } } }); return this; }, sortForId(){ this.obj.sort((item1,item2)=>item1.id-item2.id); return this; }, /** * @description 返回處理結果 * @return {Array|*} */ end(){ return this.obj; } } //暴露構造函數接口 return function (obj) { return new handle(obj); } })(); let students=[ { id:5, name:'守候', sex:'男', age:'', }, { id:2, name:'浪跡天涯', sex:'男', age:'' }, { id:5, name:'守候', sex:'', age:'' }, { id:3, name:'鴻雁', sex:'', age:'20' } ]; //根據id去重和設置'--' students=ec(students).unique().setInfo().end(); console.log(students)
結果仍是同樣,只是增長了一個方法,方便鏈式調用。
關於實現鏈式調用,這個確定是會增長代碼的,若是調用的方法並非一些經常使用,通用的方法的話,只是處理一些特殊格式的數據的方法(如上實例),不建議花費時間,實現鏈式調用,普通調用就好。若是是一些經常使用的函數的封裝,就建議使用鏈式調用。
在上面的實例裏面,相信你們都看到了,遵照單一職責的好處,可是單一職責也有缺點,就是會增長代碼的複雜程度。
在市面上,也有API是違反單一職責的。
JQuery 的 html() 方法,既能夠獲取 innerHTML ,也能夠設置 innerHTML 。 attr ()既能夠獲取 DOM 元素的某一個屬性,也能夠設置 DOM 元素的某一個屬性。
在維護上面,這樣的代碼,可能會給維護增長難度,可是對於使用者而言,這樣簡化了使用。這應該是一個取捨關係,取什麼,舍什麼。這個就是具體狀況具體分析。
今天的例子就到這裏了,這個例子,解釋降解函數單一原則會有什麼好處。這個例子比上篇文章的例子還要簡單。你們看不明白,把代碼拷貝在瀏覽器上運行,就很好理解。若是你們對這個例子有什麼更好的建議,或者代碼上有什麼問題,歡迎在評論區留言,你們多交流,相互學習。
---------------------華麗的分割線---------------------
想了解更多,關注關注個人微信公衆號:守候書閣