5 советов по написанию лучших условных операторов JavaScript

внешний интерфейс GitHub JavaScript Программа перевода самородков
5 советов по написанию лучших условных операторов JavaScript

При использовании 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:

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,внешний интерфейс,задняя часть,блокчейн,товар,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.