{"componentChunkName":"component---src-templates-post-js","path":"/javascript/5-sovetov-kak-luchshe-pisat-uslovnie-konstrukcii-v-javascript/","result":{"pageContext":{"slug":"5-sovetov-kak-luchshe-pisat-uslovnie-konstrukcii-v-javascript","content":"\n<p>В этой статье рассказывается о том, как писать условные конструкции лучше, чем вы к этому скорее всего привыкли и наглядно, прямо на примерах показывается, как это делать в сравнении с обычными методами.</p>\n\n\n\n<p class=\"author\"><em>Перевод статьи&nbsp;</em><a href=\"https://scotch.io/bar-talk/5-tips-to-write-better-conditionals-in-javascript\"><em>5 Tips to Write Better Conditionals in JavaScript</em></a></p>\n\n\n\n<h2><strong>Используйте Array.includes в случае с множественным критерием</strong> выборки</h2>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>// условие\nfunction test(fruit) {\n  if (fruit == 'apple' || fruit == 'strawberry') {\n    console.log('red');\n  }\n}</code></pre>\n\n\n\n<p id=\"86d4\">На первый взгляд пример выше выглядит вполне хорошо. Однако, что же будет, если у нас станет больше красных фруктов. К примеру ещё добавится вишня (<code>cherry</code>) или клюква (<code>cranberries</code>)? Будем ли мы расширять условие с помощью дополнительных&nbsp;<code>||</code>?</p>\n\n\n\n<p id=\"c6a3\">Мы можем&nbsp;свободно переписать условие,&nbsp;<a href=\"https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/includes\">с использованием&nbsp;</a><code><a href=\"https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/includes\">Array.includes</a></code>. Смотрите, как это просто:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit) {\n  //  Выгружаем условия в массив\n  const redFruits = &#91;'apple', 'strawberry', 'cherry', 'cranberries'];\n\n  if (redFruits.includes(fruit)) {\n    console.log('red');\n  }\n}</code></pre>\n\n\n\n<p>Тут мы выгружаем список красных фруктов (<code>redFruits</code>) в массив. Так наш код будет выглядеть чище.</p>\n\n\n\n<h2><strong>Меньше вложений с ранним выходом из функции</strong></h2>\n\n\n\n<p id=\"f3df\">Давайте расширим предыдущий пример и включим в него ещё два условия.</p>\n\n\n\n<p id=\"d2a4\">Если нет фруктов, то выкинем ошибку.</p>\n\n\n\n<p id=\"3122\">Выведем в консоль сообщение, что фруктов больше 10.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit, quantity) {\n  const redFruits = &#91;'apple', 'strawberry', 'cherry', 'cranberries'];\n\n  //  Условие 1: fruit должен иметь значение\n  if (fruit) {\n    //  Условие 2: он должен быть красным\n    if (redFruits.includes(fruit)) {\n      console.log('red');\n\n      //  Условие 3: должно быть большое количество\n      if (quantity > 10) {\n        console.log('big quantity');\n      }\n    }\n  } else {\n    throw new Error('No fruit!');\n  }\n}\n\n// test results\ntest(null); // error: No fruits\ntest('apple'); // print: red\ntest('apple', 20); // print: red, big quantity</code></pre>\n\n\n\n<p id=\"cb35\">А теперь, посмотрите на код выше, что у нас есть?</p>\n\n\n\n<p id=\"eefa\">1&nbsp;<code>if/else</code>, который фильтрует неверные условия</p>\n\n\n\n<p id=\"f771\">3 уровня вложения (условия 1, 2 и 3)</p>\n\n\n\n<p id=\"2a98\">Главное правило которому лично я стараюсь следовать &#8212; это всегда делать ранний выход из функции при обнаружении изначально неверного условия.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>/_ Раннее завершение функции, если найдено неверное условие _/\n\nfunction test(fruit, quantity) {\n  const redFruits = &#91;'apple', 'strawberry', 'cherry', 'cranberries'];\n\n  //  Условие 1: выдача ошибки сразу\n  if (!fruit) throw new Error('No fruit!');\n\n  //  Условие 2: должно быть красным\n  if (redFruits.includes(fruit)) {\n    console.log('red');\n\n    //  Условие 3: большое количество\n    if (quantity > 10) {\n      console.log('big quantity');\n    }\n  }\n}</code></pre>\n\n\n\n<p id=\"6f9b\">Таким образом у нас на один уровень вложения меньше. Такой подход особенно хорош тогда, когда у вас реально длинное условие&nbsp;<code>if</code>&nbsp;(представьте, если бы вам пришлось скролить к самому концу кода, чтобы узнать, есть ли там else. Это же обалдеть можно)</p>\n\n\n\n<p id=\"6118\">Дальше мы можем ещё больше сократить вложения&nbsp;<code>if</code>, инвертируя условие с ранним выходом из функции. Посмотрите на второе условие ниже и всё увидите:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>/_ ранний выход из функции, если найдено неверное условие _/\nfunction test(fruit, quantity) {\n  const redFruits = &#91;'apple', 'strawberry', 'cherry', 'cranberries'];\n\n  if (!fruit) throw new Error('No fruit!');  // Условие 1: выдача ошибки сразу\n  if (!redFruits.includes(fruit)) return;  Условие 2: стоп, если фрукт не красный\n\n  console.log('red');\n\n  //  Условие 3: количество должно быть больше 10\n  if (quantity > 10) {\n    console.log('big quantity');\n  }\n}</code></pre>\n\n\n\n<p id=\"7b61\">Инвертируя условия во втором случае, наш код становится свободным от вложений. Этот подход полезен тогда, когда у нас довольно длинная логика условия и нам надо отменить последующий процесс если условие не удовлетворено.</p>\n\n\n\n<p id=\"4ff6\">Однако, это не то правило, которого нужно безукоризненно придерживаться. Спросите себя сами, эта версия (без вложения) лучше/более читабельная, чем предыдущая (второе условие с вложением)?</p>\n\n\n\n<p id=\"e011\">Лично для меня подходит предыдущая версия (второе условие с вложением). И вот почему:</p>\n\n\n\n<p id=\"f6bc\">Код короче и проще, он куда понятнее с вложенным&nbsp;<code>if</code>.</p>\n\n\n\n<p id=\"b50c\">Инвертирование условия может нагрузить в плане логики и заставить лишний раз подумать.</p>\n\n\n\n<p id=\"ed9b\">Как вывод, всегда стремитесь к наименьшему вложению и раннему выходу из функции, но не пренебрегайте ими.</p>\n\n\n\n<h1 id=\"12df\"><strong>Применение дефолтных параметров функции и деструктуризация</strong></h1>\n\n\n\n<p id=\"6b67\">Я полагаю, что код ниже может выглядеть для вас вполне знакомым, нам часто нужно проверять&nbsp;<code>null</code>/<code>undefined</code>&nbsp;и назначать дефолтные значения во время работы с JavaScript:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit, quantity) {\n  if (!fruit) return;\n  const q = quantity || 1; //  Если не указывается количество, то по-дефолту будет 1\n\n  console.log(`We have ${q} ${fruit}!`);\n}\n\n//test results\ntest('banana'); // We have 1 banana!\ntest('apple', 2); // We have 2 apple!</code></pre>\n\n\n\n<p>На самом деле мы можем избавиться от переменной&nbsp;<code>q</code>, указав дефолтные параметры функции.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit, quantity = 1) { // Если не указывается количество, до по-дефолту будет 1\n  if (!fruit) return;\n  console.log(`We have ${quantity} ${fruit}!`);\n}\n\n//test results\ntest('banana'); // We have 1 banana!\ntest('apple', 2); // We have 2 apple!</code></pre>\n\n\n\n<p>Куда проще и интуитивно понятнее, не так ли? Пожалуйста, обратите внимание на то, что каждый параметр может иметь своё собственное дефолтное значение. Для примера, мы можем указать дефолтное значение для&nbsp;<code>fruit</code>:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit = 'unknown', quantity = 1)</code></pre>\n\n\n\n<p>А что если&nbsp;<code>fruit&nbsp;</code>это объект? Можем ли мы назначить дефолтный параметр?</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit) { \n  //  выводим название фрукта, если его указывают\n  if (fruit &amp;&amp; fruit.name)  {\n    console.log (fruit.name);\n  } else {\n    console.log('unknown');\n  }\n}\n\n//test results\ntest(undefined); // unknown\ntest({ }); // unknown\ntest({ name: 'apple', color: 'red' }); // apple</code></pre>\n\n\n\n<p>Посмотрите на пример выше, там нам надо вывести имя фрукта, если оно доступно или мы выведем в консоль&nbsp;<code>unknown</code>. Мы можем смело избежать объявления условия&nbsp;<code>fruit &amp;&amp; fruit.name</code>&nbsp;с помощью дефолтных параметров функции и деструктуризации.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>//  назначаем дефолтный пустой объект {}\nfunction test({name} = {}) {\n  console.log (name || 'unknown');\n}\n\n//test results\ntest(undefined); // unknown\ntest({ }); // unknown\ntest({ name: 'apple', color: 'red' }); // apple</code></pre>\n\n\n\n<p id=\"b51f\">Так как нам нужно только свойство name от&nbsp;<code>fruit</code>, мы можем деструктуризировать параметр, используя&nbsp;<code>{name}</code>, затем мы можем использовать name, как переменную в нашем коде, вместо fruit.name.</p>\n\n\n\n<p id=\"18b6\">Мы также назначаем пустой объект&nbsp;<code>{}</code>, как дефолтное значение. Если мы так не сделаем, то получим ошибку при выполнении&nbsp;<code>test(undefined)&nbsp;</code>— Cannot destructure property name of ‘<code>undefined</code>’ or ‘<code>null</code>’. Потому что тут нет свойства name в&nbsp;<code>undefined</code>.</p>\n\n\n\n<p id=\"35be\">Если вы не против использовать сторонние библиотеки, то есть несколько способов сократить проверку&nbsp;<code>null</code>:</p>\n\n\n\n<p id=\"ba45\">Используйте функцию&nbsp;<code><a href=\"https://lodash.com/docs/4.17.10#get\">get</a></code><a href=\"https://lodash.com/docs/4.17.10#get\">&nbsp;из Lodash</a></p>\n\n\n\n<p id=\"fea3\">Используйте&nbsp;<a href=\"https://github.com/facebookincubator/idx\">idx от Facebook (c Babeljs)</a></p>\n\n\n\n<p id=\"dcbb\">Вот пример с Lodash:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(fruit) {\n  console.log(__.get(fruit, 'name', 'unknown'); //  Получает name у fruit, если его нет, то назначается ‘unknown’.\n}\n\n//test results\ntest(undefined); // unknown\ntest({ }); // unknown\ntest({ name: 'apple', color: 'red' }); // apple</code></pre>\n\n\n\n<p>Вы можете запустить&nbsp;<a href=\"http://jsbin.com/bopovajiye/edit?js,console\">демо код тут</a>. Кроме того, если вы фанат Функционального Програмирования, вы можете&nbsp;<a href=\"https://github.com/lodash/lodash/wiki/FP-Guide\">выбрать Lodash fp</a>, функциональную версию Lodash. Там метод изменится с&nbsp;<code>get</code>&nbsp;на&nbsp;<code>getOr</code>).</p>\n\n\n\n<h2 id=\"0cc6\">Предпочитайте Map / Объект  вместо Switch</h2>\n\n\n\n<p id=\"18ee\">Давайте посмотрим на пример ниже, тут нам надо получить фрукты по их цвету:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>function test(color) {\n  //  используйте case, для выбора фруктов по цвету\n  switch (color) {\n    case 'red':\n      return &#91;'apple', 'strawberry'];\n    case 'yellow':\n      return &#91;'banana', 'pineapple'];\n    case 'purple':\n      return &#91;'grape', 'plum'];\n    default:\n      return &#91;];\n  }\n}\n\n//test results\ntest(null); // &#91;]\ntest('yellow'); // &#91;'banana', 'pineapple']</code></pre>\n\n\n\n<p>Кажется, что в коде выше всё правильно, но мне он кажется довольно громоздким. Тот же результат можно получить с помощью объект литерала и более чистого синтаксиса:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>//  применяем объект литерал, чтобы найти фрукты по цвету\n  const fruitColor = {\n    red: &#91;'apple', 'strawberry'],\n    yellow: &#91;'banana', 'pineapple'],\n    purple: &#91;'grape', 'plum']\n  };\n\nfunction test(color) {\n  return fruitColor&#91;color] || &#91;];\n}</code></pre>\n\n\n\n<p>Или вы можете использовать&nbsp;<code>Map</code>, чтобы достичь того же результата:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>//  используйте Map, чтобы найти фрукты по цвету\n  const fruitColor = new Map()\n    .set('red', &#91;'apple', 'strawberry'])\n    .set('yellow', &#91;'banana', 'pineapple'])\n    .set('purple', &#91;'grape', 'plum']);\n\nfunction test(color) {\n  return fruitColor.get(color) || &#91;];\n}</code></pre>\n\n\n\n<p id=\"c6f7\"><code>Map</code>&nbsp;это тип объекта, который появился в ES2015 и позволяет вам хранить данные как&nbsp;<strong>key</strong>&nbsp;<strong>value</strong>&nbsp;(ключ и его значение).</p>\n\n\n\n<p id=\"9f16\">А теперь вопрос. Нужно ли нам прекратить использование&nbsp;<code>switch</code>? Не ограничивайте себя этим. Лично я использую объект литералы, когда это возможно, но я бы не стал выставлять жесткие ограничения в этом плане, используйте то, что больше подходит под конкретный случай.</p>\n\n\n\n<p id=\"7568\">У Todd Motto есть интересная статья, в которой он углубляется в вопрос использования switch и объект литералов,&nbsp;<a href=\"https://toddmotto.com/deprecating-the-switch-statement-for-object-literals/\">тут вы можете её прочитать</a>.</p>\n\n\n\n<h2 id=\"526a\"><strong>TL;DR Рефакторим</strong></h2>\n\n\n\n<p id=\"f5f8\">Для примера выше, на самом деле, мы можем отрефакторить код с помощью <code>Array.filter</code>.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const fruits = &#91;\n    { name: 'apple', color: 'red' }, \n    { name: 'strawberry', color: 'red' }, \n    { name: 'banana', color: 'yellow' }, \n    { name: 'pineapple', color: 'yellow' }, \n    { name: 'grape', color: 'purple' }, \n    { name: 'plum', color: 'purple' }\n];\n\nfunction test(color) {\n  //  используем Array.filter, чтобы найти фрукты по цвету\n\n  return fruits.filter(f => f.color == color);\n}</code></pre>\n\n\n\n<p>Всегда есть больше одного способа достигнуть одного и того же результата. Мы увидели 4 для одного и того же примера. В общем, кодить очень даже весело!</p>\n\n\n\n<h2>Используйте Array.every или Array.some для всех или для частичных критериев</h2>\n\n\n\n<p>Последний совет скорее касается применения сравнительно новой функции массивов, с помощью которой можно значительно сократить ваш код. Посмотрите на пример ниже, тут мы хотим проверить все ли фрукты красного цвета:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const fruits = &#91;\n    { name: 'apple', color: 'red' },\n    { name: 'banana', color: 'yellow' },\n    { name: 'grape', color: 'purple' }\n  ];\n\nfunction test() {\n  let isAllRed = true;\n\n  //  Условие: все фрукты должны быть красными\n  for (let f of fruits) {\n    if (!isAllRed) break;\n    isAllRed = (f.color == 'red');\n  }\n\n  console.log(isAllRed); // false\n}</code></pre>\n\n\n\n<p>Тут всё так долго, мы вполне можем сократить число строк с помощью&nbsp;<code>Array.every</code>:</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const fruits = &#91;\n    { name: 'apple', color: 'red' },\n    { name: 'banana', color: 'yellow' },\n    { name: 'grape', color: 'purple' }\n  ];\n\nfunction test() {\n  //  Короткий способ выставления условия\n  const isAllRed = fruits.every(f => f.color == 'red');\n\n  console.log(isAllRed); // false\n}</code></pre>\n\n\n\n<p>Теперь всё куда опрятнее, да? Таким же образом мы можем проверить есть ли в нашем массиве красные фрукты, для этого мы можем просто использовать <code>Array.some</code> в одну строку.</p>\n\n\n\n<pre class=\"wp-block-code javascript\"><code>const fruits = &#91;\n    { name: 'apple', color: 'red' },\n    { name: 'banana', color: 'yellow' },\n    { name: 'grape', color: 'purple' }\n];\n\nfunction test() {\n  //  Условие: есть ли красные фрукты в массиве\n  const isAnyRed = fruits.some(f => f.color == 'red');\n\n  console.log(isAnyRed); // true\n}</code></pre>\n\n\n\n<p></p>\n","type":"js","date":"2021-02-03T19:56:19.000Z","acf":{"seo_desc":"В этой статье рассказывается о том, как писать условные конструкции лучше, чем вы к этому скорее всего привыкли и наглядно, прямо на примерах показывается, как это делать в сравнении с обычными методами.","keywords":"условные конструкции javascript, условия в js, условные конструкции в js","pub_date":"2019-02-25","tags":"JavaScript, JavaScript советы"},"title":"5 советов как лучше писать условные конструкции в JavaScript","id":"c821764c-39f6-52e4-bbfe-9635eb426503","excerpt":"<p>В этой статье рассказывается о том, как писать условные конструкции лучше, чем вы к этому скорее всего привыкли и наглядно, прямо на примерах показывается, как это делать в сравнении с обычными методами.</p>\n","featured_media":{"source_url":"https://stasonmars.ru/wp/wp-content/uploads/2021/02/uslconstrukciifkjnsdkj.jpg"},"interesting":[{"title":"15 методов работы с элементами про которые вы возможно не слышали","slug":"15-metodov-raboty-s-elementami-pro-kotorie-vy-ne-slyshaly-vozmozhno","type":"js"},{"title":"JavaScript. Почему 3 + true = 4? И другие хитрые уравнения приведения типов","slug":"javascript-pochemu-3true4-i-drugie-hitrye-uravneniya-privedeniya-tipov","type":"js"},{"title":"7 полезных уловок с rest параметрами и spread операторами на JavaScript объектах","slug":"7-poleznyh-ulovok-s-rest-parametrami-i-spread-operatorom-na-javascript-objectah","type":"js"}]}},"staticQueryHashes":["3576131997","63159454"]}