May 31, 2021 Article blog
1. 1. Use Array.includes for multiple judgments
2. 2. Less nesting, return as early as possible
3. 3. Use the default parameters and deconstruct
4. 4. Prefer object traversal to Switch statements
5. TL;DR; Reconstruct the syntax
6. 5. Use Array.every and Array.some for all/partial judgments
- 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
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.
Let's expand the previous example to include two conditions.
fruit
is passed in, an error is thrown
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:
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:
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.
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:
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
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
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.
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
}
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.