- Оригинальный адрес:5 Tips to Write Better Conditionals in JavaScript
- Оригинальный автор:Jecelyn Yeen
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:Hopsken
- Корректор:ThomasWhyne Park-ma
При использовании JavaScript нам часто приходится писать много условных операторов. Вот пять советов, которые позволят вам писать более чистые и красивые условные операторы.
1. Используйте массив. Усилия для обработки нескольких условий
Возьмите каштан 🌰:
// 条件语句
function test(fruit) {
if (fruit == 'apple' || fruit == 'strawberry') {
console.log('red');
}
}
На первый взгляд кажется, что в этом нет ничего страшного. Однако что, если бы мы хотели подобрать больше красных фруктов, скажем, «вишню» и «клюкву»? мы должны использовать больше||
расширить это утверждение?
мы можем использоватьArray.includes
(Array.includes)Перепишите приведенное выше условное предложение.
function test(fruit) {
// 把条件提取到数组中
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}
}
мы кладем红色的水果
(условия) извлекаются в массив, благодаря чему наш код выглядит чище.
2. Пишите меньше вложений, возвращайтесь раньше
Добавим к предыдущему примеру два условия:
- Выдает ошибку, если фрукты не предоставлены.
- Если количество фруктов больше 10, выведите его.
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
// 条件 1:fruit 必须有值
if (fruit) {
// 条件 2:必须为红色
if (redFruits.includes(fruit)) {
console.log('red');
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity');
}
}
} else {
throw new Error('No fruit!');
}
}
// 测试结果
test(null); // 报错:No fruits
test('apple'); // 打印:red
test('apple', 20); // 打印:red,big quantity
Давайте внимательнее посмотрим на код выше, у нас есть:
- 1 оператор if/else для фильтрации недопустимых условий
- 3 уровня вложенности операторов if (условия 1, 2 и 3)
Лично я придерживаюсь общего правила:Вернуться раньше, когда обнаружено недопустимое условие.
/_ 当发现无效条件时尽早返回 _/
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, чтобы увидеть, как это делается:
/_ 当发现无效条件时尽早返回 _/
function test(fruit, quantity) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (!fruit) throw new Error('No fruit!'); // 条件 1:尽早抛出错误
if (!redFruits.includes(fruit)) return; // 条件 2:当 fruit 不是红色的时候,直接返回
console.log('red');
// 条件 3:必须是大量存在
if (quantity > 10) {
console.log('big quantity');
}
}
Изменив условие условия 2, наш код теперь свободен от вложенности. Этот трюк хорошо работает, когда логическая цепочка нашего кода длинная, и мы не хотим выполнять следующий процесс, когда определенное условие не выполняется.
Однако нетжесткие правилапопросить вас сделать это. Вам решать, будет ли эта версия кода (без вложенности) лучше и читабельнее для вас, чем предыдущая версия (условие 2 с вложенностью)?
Если бы это был я, я бы выбрал предыдущую версию (условие 2 имеет вложенность). причина в следующем:
- Такой код относительно короткий и простой, а вложенный if делает структуру более понятной.
- Кондициональная инверсия приводит к большему количеству мыслительных процессов (увеличение когнитивной нагрузки).
следовательно,Всегда стремитесь к меньшему количеству вложений, возвращайтесь раньше, но не переусердствуйте.. Если интересно, вот статья на эту тему и обсуждение на 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;
const q = quantity || 1; // 如果没有提供 quantity,默认为 1
console.log(`We have ${q} ${fruit}!`);
}
//测试结果
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('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
Это проще и понятнее? Обратите внимание, что все параметры функции могут иметь свои значения.По умолчанию. Например, мы также можемfruit
Укажите значение по умолчанию:function test(fruit = 'unknown', quantity = 1)
.
то еслиfruit
Это объект? Можем ли мы по-прежнему использовать параметры по умолчанию?
function test(fruit) {
// 如果有值,则打印出来
if (fruit && fruit.name) {
console.log (fruit.name);
} else {
console.log('unknown');
}
}
//测试结果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
Глядя на приведенный выше пример, когда существует атрибут имени фрукта, мы хотим напечатать его, иначе напечатать «неизвестно». Мы можем избежать записи параметров по умолчанию и деструктуризации присваиваний.fruit && fruit.name
это условие.
// 解构 —— 只得到 name 属性
// 默认参数为空对象 {}
function test({name} = {}) {
console.log (name || 'unknown');
}
//测试结果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
Поскольку нам нужны только плодыname
свойства, мы можем использовать{name}
чтобы деконструировать его, чтобы мы могли использовать его в нашем кодеname
переменная для заменыfruit.name
.
мы также используем{}
как его значение по умолчанию. Если мы этого не делаем, мы выполняемtest(undefined)
когда вы получаете сообщение об ошибкеCannot destructure property name of 'undefined' or 'null'.
,потому чтоundefined
не наname
Атрибуты. (Примечание переводчика: на самом деле это не очень точно, потому что деструктурирование применяется только к объектам (Object), а не потому, чтоundefined
не наname
свойства (ни для пустых объектов). Ссылаться наПрисвоение деструктуризации - MDN)
Если вы не возражаете против использования сторонней библиотеки, есть несколько способов уменьшить количество проверок на null:
- использоватьLodash getфункция
- Открытый исходный код с использованием FacebookidxБиблиотеки (требуется Babeljs)
Вот пример использования Lodash:
// 使用 lodash 库提供的 _ 方法
function test(fruit) {
console.log(_.get(fruit, 'name', 'unknown'); // 获取属性 name 的值,如果没有,设为默认值 unknown
}
//测试结果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
ты сможешьздесьЗапустите демонстрационный код. Кроме того, если вы предпочитаете функциональное программирование (FP), вы можете использоватьLodash fp- функциональная версия Lodash (название метода становитсяget
илиgetOr
).
4. Карта/Объект может быть лучшим выбором, чем переключатель
Давайте посмотрим на следующий пример, мы хотим распечатать различные фрукты в зависимости от цвета:
function test(color) {
// 使用 switch case 来找到对应颜色的水果
switch (color) {
case 'red':
return ['apple', 'strawberry'];
case 'yellow':
return ['banana', 'pineapple'];
case 'purple':
return ['grape', 'plum'];
default:
return [];
}
}
//测试结果
test(null); // []
test('yellow'); // ['banana', 'pineapple']
Приведенный выше код не выглядит неправильным, но лично он выглядит многословным. Тот же результат может быть достигнут с помощью литералов объектов с более кратким синтаксисом:
// 使用对象字面量来找到对应颜色的水果
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function test(color) {
return fruitColor[color] || [];
}
Кроме того, вы также можете использоватьMapдля достижения того же эффекта:
// 使用 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 и литералы объектов, на которые вы, возможно, захотите взглянуть.
Lazy Edition: синтаксис рефакторинга
Фактически, в приведенном выше примере мы можем реорганизовать наш код, чтобы использовать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) {
// 使用 Array filter 来找到对应颜色的水果
return fruits.filter(f => f.color == color);
}
Никогда не бывает одного способа решить проблему. Для этого примера мы показываем четыре реализации. Кодирование — это весело!
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
}
Суммировать
Давайте вместе писать более читаемый код. Надеюсь, эта статья поможет вам.
Вот и все. Удачного кодирования!
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из ИнтернетаНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,товар,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.