1. Введение
В прошлой статье писали про рефакторинг для добавления расширяемости и говорили про открытый и закрытый принцип. Темп обучения не может остановиться на этом, в сегодняшней статье будет упомянут еще один принцип развития: принцип единой ответственности. С точки зрения непрофессионала, функция делает только одну вещь.Нижеследующее исследует принцип единой ответственности на нескольких примерах.
2. Представление единоличной ответственности
Определение единой ответственности можно понимать как: объект или метод, который делает только одну вещь.
Примеров соблюдения одной обязанности слишком много, и ниже приводится краткий список.
Нативные условия API
trimRight() и trimLeft(): trimRight отвечает только за удаление пробелов справа и больше ни за что. trimLeft отвечает только за удаление пробела справа и больше ни за что.
concat(): concat отвечает только за объединение двух или более массивов и возврат результата. Никаких операций по удалению массивов не требуется.
toFixed(): toFixed округляет только значения типа Number до указанного количества знаков после запятой. Никакие другие операции выполняться не будут.
jQuery-API
$.each() отвечает только за обход, что делать, а потом делать самому.
css() отвечает только за установку стиля DOM, а не innerHTML.
animate() отвечает только за выполнение пользовательских анимаций наборов свойств CSS, и никакие другие операции не задействованы.
Так говорят, но вы можете немного смутиться, когда посмотрите на это, и вы не сможете увидеть преимущества следования единому принципу Давайте рассмотрим пример.
3. Пример — обработка массива
Следующий пример:
Имеется пакет введенной информации о студентах, но данные дублируются, и данные необходимо дедуплицировать в соответствии с идентификатором. Затем измените пустую информацию на «--».
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排序
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);
Таким образом, даже если в будущем требования изменятся в контролируемом диапазоне, его можно будет использовать в гибких комбинациях, а функции можно использовать повторно.
Если вы чувствуете, что непрерывное назначение студентов является проблематичным, вы можете изучить метод цепных вызовов 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)
Результат тот же, но добавлен метод для облегчения связанных вызовов.
Что касается реализации цепных вызовов, то это однозначно увеличит код.Если вызываемый метод не является какими-то общими и общими методами, это всего лишь метод обработки данных в каких-то специальных форматах (как в приведенном выше примере), то это не рекомендуется тратить время на реализацию цепного звонка, подойдет обычный звонок. Если это инкапсуляция некоторых часто используемых функций, рекомендуется использовать цепные вызовы.
4. Один нарушение принципа долга
Я полагаю, что в приведенных выше примерах все увидели преимущества соблюдения единой ответственности, но у единой ответственности есть и недостатки, то есть она увеличит сложность кода.
На рынке также есть API, которые нарушают единую ответственность.
Метод JQuery html() может либо получить innerHTML, либо установить innerHTML. attr() может либо получить атрибут элемента DOM, либо установить атрибут элемента DOM.
С точки зрения обслуживания такой код может усложнить обслуживание, но для пользователей он упрощает его использование. Это должны быть компромиссные отношения, что взять, от чего отказаться. Это индивидуальный анализ.
5. Резюме
Вот и все, что касается сегодняшнего примера, этого примера, объясняющего, как единый принцип функции деградации может быть полезен. Этот пример проще, чем в предыдущей статье. Не всем это понятно, это легко понять, если скопировать код и запустить его в браузере. Если у вас есть какие-либо лучшие предложения для этого примера или если есть какие-либо проблемы с кодом, оставьте сообщение в области комментариев, чтобы мы могли больше общаться и учиться друг у друга.
---------------------Великолепная разделительная линия----------------------
Хотите узнать больше, обратите внимание на мой публичный аккаунт WeChat: В ожидании книжного магазина