Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Write 5 codes for JavaScript conditional statements


May 31, 2021 Article blog


Table of contents


  • Original address: 5 Tips to Write Better Conditionals in JavaScript

  • Translated by: Alibaba Cloud Translation Group

  • Translator: Sleeping Cloud (Yang Tao)

  • Proofreader: Also Tree, McSkiller

When working with JavaScript, we often deal with conditional statements, and here are 5 suggestions for you to write better/cleaner conditional statements.

1. Array.includes for multiple judgments

2. Less nesting, return as early as possible

3. Use the default parameters and deconstruct

4. Tends to traverse objects rather than Switch statements

5. Use Array.every and Array.some for all/partial judgments

6. Summary

1. Use Array.includes for multiple judgments

Let's look at the following example:

// condition
function test(fruit) {
  if (fruit == 'apple' || fruit == 'strawberry') {
    console.log('red');
  }
}

At first glance, the above example looks fine. W hat if we had more red fruits called cherry and cranberries Are we going to extend conditional statements with more ||

We can override conditional Array.includes with Array.includes.

function test(fruit) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];


  if (redFruits.includes(fruit)) {
    console.log('red');
  }
}

We extract 红色的水果(red fruits) criteria into an array. This makes the code look cleaner.

2. Less nesting, return as early as possible

Let's expand the previous example to include two conditions.

  • If no argument fruit is passed in, an error is thrown
  • Accepts the quantity parameter and prints it when quantity is greater than 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

In the above code, we have:

  • 1 if/else statement filters out invalid statements
  • 3-tier if nested statements (conditions 1, 2 , 3)

The rule I personally follow is generally to return as early as possible when invalid conditions are found.

/_ 当发现无效语句时,尽早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');
    }
  }
}

As a result, we're missing a layer of nested statements. This coding style is great, especially if you have a long if statement (imagine you need to scroll to the bottom to know that there are else statements, which is not cool)

We can further reduce if nesting as early as possible by inverting the judgment criteria. Here's how we handle Judgment Condition 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');
  }
}

By inverting condition 2, our code avoids nested statements. This technique is useful when we need to make long logical judgments, especially if we want to be able to stop processing when conditions are not met.

And it's not hard to do that. Ask yourself, is this version (not nested) better and more readable than the previous (two-tier conditional nesting)?

But for me, I'll keep the previous version (with two layers nested). This is because:

  • The code is shorter and straightforward, with clearer if nesting
  • Inverted judgment conditions may increase the burden of thinking (increase cognitive load)

Therefore, you should try to reduce nesting and return as early as possible, but not overdo it. If you're interested, take a look at an article on this topic and a discussion on StackOverflow.

  • Avoid Else, Return Early by Tim Oxley
  • StackOverflow discussion on if/else coding style

3. Use the default parameters and deconstruct

I guess the following code you might be familiar with, in JavaScript we always need to check the value of null / undefined and specify the default value:

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!

In fact, we can eliminate variable q by declaring the default function argument.

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!

It's more intuitive, isn't it? Note that each declaration has its own default parameters.

For example, we can also assign a default value to fruit function test(fruit = 'unknown', quantity = 1)

What if fruit is an object? Can we assign a default parameter?

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

Looking at the example above, we want to print the name property that might exist in the fruit object. O therwise we will print unknown. We can avoid judging the condition fruit && fruit.name default parameters and deconstructing it

// 解构 - 仅仅获取 name 属性
// 为其赋默认值为空对象
function test({name} = {}) {
  console.log (name || 'unknown');
}


// test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple

Since we only need name property, we can deconstruct the parameters with {name} name, and then we can use the variable name fruit.name

We also need to declare the empty object {} as the default. I f we don't, when you execute test(undefined) you get an error that can't be deconstructed to undefined or null. Because there is no name property in undefined.

If you don't mind using third-party libraries, there are some ways to reduce null checks:

  • Use the Lodash get function
  • Use Facebook's open source idx library (with Babeljs)

This is an example of using Lodash:

function test(fruit) {
  // 获取属性名,如果属性名不可用,赋默认值为 unknown
  console.log(__.get(fruit, 'name', 'unknown'); 
}


// test results
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple

You can run demo code in jsbin. In addition, if you are a fan of functional programming, you may choose to use Lodash fp, Lodash's functional version (the method changes to get or getOr

4. Prefer object traversal to Switch statements

Let's look at the following example, and we want to print out the fruit based on color:

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']

The code above doesn't look wrong, but I've found some cumbersome. Implementing the same result with object traversal, the syntax looks simpler:

const fruitColor = {
  red: ['apple', 'strawberry'],
  yellow: ['banana', 'pineapple'],
  purple: ['grape', 'plum']
};


function test(color) {
  return fruitColor[color] || [];
}

Or you can use Map to achieve the same result:

  const fruitColor = new Map()
    .set('red', ['apple', 'strawberry'])
    .set('yellow', ['banana', 'pineapple'])
    .set('purple', ['grape', 'plum']);


function test(color) {
  return fruitColor.get(color) || [];
}

Map is an object type implemented after the ES2015 specification that allows you to store the values of key and value.

But should we ban the use of switch statements? T he answer is don't limit yourself. Personally, I'll use object traversal as much as I can, but I don't strictly adhere to it, but use a way that makes more sense for the current scenario.

Todd Motto has a more in-depth article on switch statements versus object traversal, which you can read here

TL;DR; Reconstruct the syntax

In the example above, we were able to refactor our code with Array.filter to achieve the same effect.

 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);
}

There is more than one way to achieve the same results, and we showed four above.

5. Use Array.every and Array.some for all/partial judgments

This last recommendation is more about using JavaScript Array's built-in methods to reduce the number of lines of code. Looking at the code below, we want to check if all fruits are red:

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
}

The code is so long! We can reduce the number of lines of code through 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
}

It's cleaner now, isn't it? In the same way, if we want to test for the presence of red fruits, we can do so using Array.some line of code.

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. Summary

Let's produce more readable code together. I hope you can learn something from this article.

The above is W3Cschool编程狮 on the writing of JavaScript conditional statements of the 5 codes related to the introduction, I hope to help you.