- Оригинальный адрес:5 Tips to Write Better Conditionals in JavaScript
- Оригинальный автор:ecelyn Yeen(@jecelynyeen)
- Перевод с:Команда облачных переводчиков Alibaba
- Ссылка на перевод:GitHub.com/рассветные команды/…
- Переводчик:Спящее облако (Ян Тао)
- Корректор:также дерево,Mcskiller
Работая в JavaScript, мы часто имеем дело с условными операторами, вот 5 советов, как написать более качественные/чистые условные операторы.
1. Используйте Array.includes для множественных суждений
2. Меньше вложенности, ранний возврат
3. Используйте параметры по умолчанию и деструктуризацию
4. Старайтесь перебирать объекты, а не операторы Switch.
5. Используйте Array.every и Array.some для всех/частичных суждений
6. Резюме
1. Используйте Array.includes для множественных суждений
Давайте посмотрим на следующий пример:
// condition
function test(fruit) {
if (fruit == 'apple' || fruit == 'strawberry') {
console.log('red');
}
}
На первый взгляд приведенный выше пример выглядит нормально. если бы у нас было больше именcherry
а такжеcranberries
А как насчет красных фруктов? Мы собираемся использовать больше||
расширить условное выражение?
мы можем использоватьArray.includes
(Array.includes)Перепишите условное выражение.
function test(fruit) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}
}
мы кладем红色的水果(red fruits)
Это условие оценки извлекается в массив. Таким образом, код выглядит чище.
2. Меньше вложенности, ранний возврат
Давайте расширим предыдущий пример, включив в него два условия.
- Если параметр fruit не передан, выдать ошибку
- Принимает параметр количества и печатает его, если количество больше 10
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1: fruit 必须有值
if (fruit) {
// 条件 2: 必须是red的
if (redFruits.includes(fruit)) {
console.log('red');
// 条件 3: quantity大于10
if (quantity > 10) {
console.log('big quantity');
}
}
} else {
throw new Error('No fruit!');
}
}
// 测试结果
test(null); // error: No fruits
test('apple'); // print: red
test('apple', 20); // print: red, big quantity
В приведенном выше коде мы имеем:
- 1 оператор if/else для фильтрации неверных операторов
- 3 уровня вложенных операторов if (условия 1, 2 и 3)
Я лично следую правилу: когда обнаруживается недопустимое условие,Вернитесь как можно скорее.
/_ 当发现无效语句时,尽早Return _/
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1: 尽早抛出错误
if (!fruit) throw new Error('No fruit!');
// 条件 2: 必须是红色的
if (redFruits.includes(fruit)) {
console.log('red');
// 条件 3: 必须是大质量的
if (quantity > 10) {
console.log('big quantity');
}
}
}
Таким образом, у нас на один вложенный оператор меньше. Этот стиль кодирования великолепен, особенно когда у вас есть длинные операторы if (представьте, что вам нужно прокрутить вниз, чтобы узнать, что есть операторы else, что не круто)
Мы можем еще больше уменьшить вложенность, инвертируя условие и возвращаясь раньше. См. ниже, как мы обрабатываем условие оценки 2:
/_ 当发现无效语句时,尽早Return _/
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1: 尽早抛出错误
if (!fruit) throw new Error('No fruit!');
// 条件 2: 当水果不是红色时停止继续执行
if (!redFruits.includes(fruit)) return;
console.log('red');
// 条件 3: 必须是大质量的
if (quantity > 10) {
console.log('big quantity');
}
}
Инвертируя условие 2, наш код избегает вложенных операторов. Этот метод очень полезен, когда нам нужно делать длинные логические суждения, особенно когда мы хотим иметь возможность останавливаться и обрабатывать, когда условия не выполняются.
И сделать это не сложно. Спросите себя, эта версия (без вложенности) лучше и читабельнее предыдущей (два уровня условной вложенности)?
Но для себя я бы оставил предыдущую версию (с двумя уровнями вложенности). Это потому что:
- Код короче и понятнее, и его легче включать, если вложенность
- Инвертирование условий суждения может увеличить нагрузку на мышление (увеличить когнитивную нагрузку)
Следовательно, следуетСтарайтесь свести к минимуму вложенность и вернуться пораньше, но не переусердствуйте.. Ознакомьтесь со статьей на эту тему и обсуждением на StackOverflow, если вам интересно.
- Avoid Else, Return Early by Tim Oxley
- StackOverflow discussion on if/else coding style
3. Используйте параметры по умолчанию и деструктуризацию
Я предполагаю, что следующий код, с которым вы можете быть знакомы, в JavaScript нам всегда нужно проверятьnull
/ undefined
значение и укажите значение по умолчанию:
function test(fruit, quantity) {
if (!fruit) return;
// 如果 quantity 参数没有传入,设置默认值为 1
const q = quantity || 1;
console.log(`We have ${q} ${fruit}!`);
}
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
На самом деле мы можем исключить переменную q, объявив параметры функции по умолчанию.
function test(fruit, quantity = 1) {
// 如果 quantity 参数没有传入,设置默认值为 1
if (!fruit) return;
console.log(`We have ${quantity} ${fruit}!`);
}
//test results
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
Это более интуитивно понятно, не так ли? Обратите внимание, что каждое объявление имеет свой собственныйпараметры по умолчанию.
Например, мы также можем датьfruit
Назначить значение по умолчанию:function test(fruit = 'unknown', quantity = 1)
.
еслиfruit
А если это объект? Можем ли мы назначить параметр по умолчанию?
function test(fruit) {
// 当值存在时打印 fruit 的值
if (fruit && fruit.name) {
console.log (fruit.name);
} else {
console.log('unknown');
}
}
//test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
Глядя на приведенный выше пример, мы хотим напечатать свойство имени, которое может существовать в объекте фруктов. В противном случае мы напечатаем unknown. Мы можем избежать условий суждения с помощью параметров по умолчанию и деструктуризацииfruit && fruit.name
// 解构 - 仅仅获取 name 属性
// 为其赋默认值为空对象
function test({name} = {}) {
console.log (name || 'unknown');
}
// test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
Так как нам нужно толькоname
свойства, мы можем использовать{name}
Деконструируйте параметры, тогда мы можем использовать переменныеname
заменятьfruit.name
.
Нам также нужно объявить пустые объекты{}
как значение по умолчанию. Если мы этого не сделаем, при выполненииtest(undefined)
, вы получите сообщение об ошибке, что undefined или null не могут быть уничтожены. потому что в undefined нетname
Атрибуты.
Если вы не возражаете против использования сторонней библиотеки, вот несколько способов уменьшить количество проверок на null:
- использоватьLodash getфункция
- Использование Facebook с открытым исходным кодомidxБиблиотеки (с Babeljs)
Вот пример использования Lodash:
function test(fruit) {
// 获取属性名,如果属性名不可用,赋默认值为 unknown
console.log(__.get(fruit, 'name', 'unknown');
}
// test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
ты сможешьjsbinЗапустите демонстрационный код. Помимо этого, если вы поклонник функционального программирования, вы можете использоватьLodash fp, функциональная версия Lodash (метод изменен наget
илиgetOr
).
4. Предпочитайте обход объекта оператору Switch
Давайте посмотрим на следующий пример, мы хотим распечатать фрукты в зависимости от цвета:
function test(color) {
// 使用条件语句来寻找对应颜色的水果
switch (color) {
case 'red':
return ['apple', 'strawberry'];
case 'yellow':
return ['banana', 'pineapple'];
case 'purple':
return ['grape', 'plum'];
default:
return [];
}
}
// test results
test(null); // []
test('yellow'); // ['banana', 'pineapple']
Приведенный выше код выглядит безошибочным, но я обнаружил некоторую громоздкость. Добиваясь того же результата с обходом объекта, синтаксис выглядит более лаконично:
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function test(color) {
return fruitColor[color] || [];
}
или вы также можете использоватьMapдобиться того же результата:
const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);
function test(color) {
return fruitColor.get(color) || [];
}
Map— это тип объекта, реализованный после спецификации ES2015, который позволяет хранить значения ключа и значения.
Но должны ли мы запретить использование операторов switch? Ответ заключается в том, чтобы не ограничивать себя. Лично я бы использовал обход объекта, когда это возможно, но я не придерживаюсь его строго, а использую то, что имеет больше смысла для текущего сценария.
У Тодда Мотто есть более подробная статья об операторах switch и обходе объектов, которую вы можете прочитать по адресуэто месточитать
TL;DR; синтаксис рефакторинга
В приведенном выше примере мы можем использоватьArray.filter
Рефакторинг нашего кода для достижения того же эффекта.
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'strawberry', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'pineapple', color: 'yellow' },
{ name: 'grape', color: 'purple' },
{ name: 'plum', color: 'purple' }
];
function test(color) {
return fruits.filter(f => f.color == color);
}
Существует более одного способа достижения одного и того же результата, мы показали 4 выше.
5. Используйте Array.every и Array.some для всех/частичных суждений
Это последнее предложение больше о пользу используемых встроенных методах массива JavaScript для уменьшения строк кода. Глядя на код ниже, мы хотим проверить, будут ли все фрукты красными:
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
let isAllRed = true;
// 条件:所有水果都是红色
for (let f of fruits) {
if (!isAllRed) break;
isAllRed = (f.color == 'red');
}
console.log(isAllRed); // false
}
Код такой длинный! мы можем пройтиArray.every
Уменьшите количество строк кода:
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
const isAllRed = fruits.every(f => f.color == 'red');
console.log(isAllRed); // false
}
Теперь это более лаконично, не так ли? Точно так же, если мы хотим проверить наличие красных фруктов, мы можем использоватьArray.some
Реализация одной строки кода.
const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// 条件:任何一个水果是红色
const isAnyRed = fruits.some(f => f.color == 'red');
console.log(isAnyRed); // true
}
6. Резюме
Давайте создадим более читаемый код вместе. Я надеюсь, что вы можете узнать что-то из этой статьи.
Это все контент. Счастливое кодирование!