上篇文章寫了添加擴展性方面的重構,講到了開放封閉原則。學習的步伐不能就此中止,今天的文章,將會說起開發的另外一個原則:單一職責原則。通俗點說就是一個函數只作一件事,下面將會經過幾個實例,探究單一職責原則。css
單一職責的定義能夠理解爲:一個對象或者方法,只作一件事。html
遵照單一職責的實例太多了,下面簡單列舉一下。數組
原生的API方面瀏覽器
trimRight()和trimLeft():trimRight 只負責去除右邊的空白,其它地方一律無論。 trimLeft 只負責去除右邊的空白,其它地方也一律不關。bash
concat(): concat 只負責鏈接兩個或更多的數組,並返回結果。不會涉及刪除數組的操做。微信
toFixed(): toFixed 只把 Number 類型的值四捨五入爲指定小數位數的數字。不會執行其它操做。函數
JQuery 的 API學習
$.each() 只負責遍歷,要處理什麼,本身再動手操做。動畫
css() 只負責設置 DOM 的 style ,不會設置 innerHTML 。ui
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 元素的某一個屬性。
在維護上面,這樣的代碼,可能會給維護增長難度,可是對於使用者而言,這樣簡化了使用。這應該是一個取捨關係,取什麼,舍什麼。這個就是具體狀況具體分析。
今天的例子就到這裏了,這個例子,解釋降解函數單一原則會有什麼好處。這個例子比上篇文章的例子還要簡單。你們看不明白,把代碼拷貝在瀏覽器上運行,就很好理解。若是你們對這個例子有什麼更好的建議,或者代碼上有什麼問題,歡迎在評論區留言,你們多交流,相互學習。
---------------------華麗的分割線---------------------
想了解更多,關注關注個人微信公衆號:守候書閣