摘要:就让我们看看以下几种常见的条件表达场景,如何写的漂亮!

本文分享自华为云社区《如何写出漂亮的条件表达式 - JavaScript 实现篇》,原文作者:查尔斯。

条件表达式,是我们在coding过程中永远躲不开的问题,也是我们骗代码行数最方便的东西(狗头.jpg),但作为一名程序员,我们也要追求自己的“信达雅”,下面就让我们看看以下几种常见的条件表达场景,如何写的漂亮!

  • 多条件语句
  • 多属性对象
  • 替换Switch语句
  • 默认参数与解构
  • 匹配所有或部分条件
  • 使用可选链和 Nullish 合并

多条件语句

多条件语句使用Array.includes

举个例子

function printAnimals(animal) {
if (animal === "dog" || animal === "cat") {
console.log(`I have a ${animal}`);
}
} console.log(printAnimals("dog")); // I have a dog

这种写法在条件比较少的情况下看起来没有问题,此时我们只有 2 种动物,但是如果我们有更多的条件需要判断(更多的动物)呢?如果我们继续拓展判断的条件,那么代码将会变得难以维护,而且逻辑会不清晰。

解决方法

可以使用Array.includes来重写条件语句

function printAnimals(animal) {
const animals = ["dog", "cat", "hamster", "turtle"]; if (animals.includes(animal)) {
console.log(`I have a ${animal}`);
}
} console.log(printAnimals("hamster")); // I have a hamster

在这里,我们创建了一个动物数组,以便将条件与代码的其余部分分开提取。现在,如果我们想要检查任何其他动物,我们需要做的就是添加一个新的数组项。

我们还可以在这个函数的范围之外使用 animals 变量,以便在代码的其他地方重用它。这是一种编写更清晰、更容易理解和维护的代码的方法。不是吗?

多属性对象

这是一个非常好的技巧来压缩你的代码,使它看起来更简洁。让我们以前面的示例为例,添加更多的条件。如果这个动物不是一个简单的字符串,而是一个具有某些属性的对象呢?

所以现在的要求是:

  • 如果没有动物,抛出一个错误
  • 打印动物的类型
  • 打印动物的名字
  • 打印动物的性别
const printAnimalDetails = (animal) => {
let result; // declare a variable to store the final value // condition 1: check if animal has a value
if (animal) {
// condition 2: check if animal has a type property
if (animal.type) {
// condition 3: check if animal has a name property
if (animal.name) {
// condition 4: check if animal has a gender property
if (animal.gender) {
result = `${animal.name} is a ${animal.gender} ${animal.type};`;
} else {
result = "No animal gender";
}
} else {
result = "No animal name";
}
} else {
result = "No animal type";
}
} else {
result = "No animal";
} return result;
}; console.log(printAnimalDetails()); // 'No animal' console.log(printAnimalDetails({ type: "dog", gender: "female" })); // 'No animal name' console.log(printAnimalDetails({ type: "dog", name: "Lucy" })); // 'No animal gender' console.log(
printAnimalDetails({ type: "dog", name: "Lucy", gender: "female" })
); // 'Lucy is a female dog'

上面的代码它工作得很好,但是代码很长,很难维护。如果不使用提示工具,可能会浪费一些时间来确定右括号的位置。想象将会发生什么如果代码更复杂的逻辑。很多if...else的语句!

我们可以使用三元操作符、&&条件等来重构上面的函数,但是让我们使用多个返回语句来编写更精确的代码。

const printAnimalDetails = ({ type, name, gender } = {}) => {
if (!type) return "No animal type";
if (!name) return "No animal name";
if (!gender) return "No animal gender"; // Now in this line of code, we're sure that we have an animal with all //the three properties here. return `${name} is a ${gender} ${type}`;
}; console.log(printAnimalDetails()); // 'No animal type' console.log(printAnimalDetails({ type: dog })); // 'No animal name' console.log(printAnimalDetails({ type: dog, gender: female })); // 'No animal name' console.log(printAnimalDetails({ type: dog, name: "Lucy", gender: "female" })); // 'Lucy is a female dog'

在重构版本中,还包括解构默认参数默认参数确保如果我们将 undefined 作为参数传递给方法,我们仍然有一个要解构的值,这里是一个空对象 {}。

通常,代码是在这两种方法之间编写的。

举个例子

function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"]; // condition 1: vegetable should be present
if (vegetable) {
// condition 2: must be one of the item from the list
if (vegetables.includes(vegetable)) {
console.log(`I like ${vegetable}`); // condition 3: must be large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}
} else {
throw new Error("No vegetable from the list!");
}
} printVegetablesWithQuantity(null); // No vegetable from the list!
printVegetablesWithQuantity("cabbage"); // I like cabbage
printVegetablesWithQuantity("cabbage", 20);
// 'I like cabbage`
// 'I have bought a large quantity'

现在,我们有:

  • 过滤无效条件的 if/else 语句
  • 3 层嵌套的 if 语句(条件 1、2 和 3)
  • 一个通用的规则是当发现无效条件时尽早返回。

一个通用的规则是发现无效的条件时尽早返回

function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"]; // condition 1: throw error early
if (!vegetable) throw new Error("No vegetable from the list!"); // condition 2: must be in the list
if (vegetables.includes(vegetable)) {
console.log(`I like ${vegetable}`); // condition 3: must be a large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}
}

通过这样做,我们减少了一个嵌套语句的级别。这种编码风格很好,特别是当使用长if语句时。通过反转条件并提前返回,我们可以进一步减少嵌套if。

请看下面的条件 2 是怎么做的:

function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ["potato", "cabbage", "cauliflower", "asparagus"]; if (!vegetable) throw new Error("No vegetable from the list!");
// condition 1: throw error early if (!vegetables.includes(vegetable)) return;
// condition 2: return from the function is the vegetable is not in
// the list console.log(`I like ${vegetable}`); // condition 3: must be a large quantity
if (quantity >= 10) {
console.log("I have bought a large quantity");
}
}

通过反转条件 2 的条件,代码不再具有嵌套语句。当我们有很多条件并且希望在任何特定条件不满足时停止进一步的处理时,这种技术是有用的。

因此,总是以减少嵌套和尽早返回为目标,但不要过度。

替换Switch语句

让我们看一下下面的例子,我们想要根据颜色打印水果:

function printFruits(color) {
// use switch case to find fruits by color
switch (color) {
case "red":
return ["apple", "strawberry"];
case "yellow":
return ["banana", "pineapple"];
case "purple":
return ["grape", "plum"];
default:
return [];
}
} printFruits(null); // []
printFruits("yellow"); // ['banana', 'pineapple']

上面的代码实现没有错误,但是很冗长,同样的结果可以使用更简洁的语法来实现。

// use object literal to find fruits by color
const fruitColor = {
red: ["apple", "strawberry"],
yellow: ["banana", "pineapple"],
purple: ["grape", "plum"],
}; function printFruits(color) {
return fruitColor[color] || [];
}

同样的,也可以使用 Map 来实现:

// use Map to find fruits by color
const fruitColor = new Map()
.set("red", ["apple", "strawberry"])
.set("yellow", ["banana", "pineapple"])
.set("purple", ["grape", "plum"]); function printFruits(color) {
return fruitColor.get(color) || [];
}

Map是 ES5 以来可用的对象类型,它允许存 key-value。

对于上面的示例,可以使用 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 printFruits(color) {
return fruits.filter((fruit) => fruit.color === color);
}

默认参数与解构

在使用 JavaScript 时,我们总是需要检查 null/undefined 并分配默认值或编译中断。

function printVegetablesWithQuantity(vegetable, quantity = 1) {
// if quantity has no value, assign 1 if (!vegetable) return;
console.log(`We have ${quantity} ${vegetable}!`);
}
//results
} printVegetablesWithQuantity('cabbage'); // We have 1 cabbage!
printVegetablesWithQuantity('potato', 2); // We have 2 potato!

如果蔬菜是一个对象呢?我们可以分配一个默认参数吗?

function printVegetableName(vegetable) {
if (vegetable && vegetable.name) {
console.log(vegetable.name);
} else {
console.log("unknown");
}
} printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: "cabbage", quantity: 2 }); // cabbage

在上面的示例中,我们希望打印蔬菜名(如果它可用)或打印 unknown。

我们可以通过使用默认参数&解构来避免条件if (vegetable && vegetable.name){}。

// destructing - get name property only
// assign default empty object {} function printVegetableName({ name } = {}) {
console.log(name || "unknown");
} printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: "cabbage", quantity: 2 }); // cabbage

因为我们只需要属性名,所以我们可以使用 {name} 来改变参数的结构,然后我们可以在代码中使用 name 作为变量,而不是使用 vegetable.name。

我们还将一个空对象 {} 赋值为默认值,否则在执行 printVegetableName(undefined) 时,它将给出一个错误—— Cannot destructure property name of undefined or null,因为在 undefined 中没有 name 属性。

匹配所有或部分条件

我们可以通过使用这些Array方法来减少代码行数。

下面的代码,我们想要检查是否所有的水果都是红色的:

const fruits = [
{ name: "apple", color: "red" },
{ name: "banana", color: "yellow" },
{ name: "grape", color: "purple" },
]; function test() {
let isAllRed = true; // condition: all fruits must be red
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() {
// condition: short way, all fruits must be red
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() {
// condition: if any fruit is red
const isAnyRed = fruits.some((f) => f.color == "red"); console.log(isAnyRed); // true
}

使用可选链和 Nullish 合并

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF%E9%80%89%E9%93%BE

这两个功能对于 JavaScript 编写更简洁的条件非常有用。在编写本文时,它们还没有得到完全的支持,可能需要使用Babel进行编译。

可选链接能够处理类似树的结构,而不需要显式地检查中间节点是否存在,并且Nullish与可选链接结合使用非常有效,可以确保不存在节点的默认值。

举个例子:

const car = {
model: "Fiesta",
manufacturer: {
name: "Ford",
address: {
street: "Some Street Name",
number: "5555",
state: "USA",
},
},
}; // to get the car model
const model = (car && car.model) || "default model"; // to get the manufacturer street
const street =
(car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.address.street) ||
"default street"; // request an un-existing property
const phoneNumber =
car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.phoneNumber; console.log(model); // 'Fiesta'
console.log(street); // 'Some Street Name'
console.log(phoneNumber); // undefined

因此,如果我们想打印出来,如果汽车制造商来自美国,代码应该是这样的:

const isManufacturerFromUSA = () => {
if (
car &&
car.manufacturer &&
car.manufacturer.address &&
car.manufacturer.address.state === "USA"
) {
console.log("true");
}
}; checkCarManufacturerState(); // 'true'

可以清楚地看到,对于更复杂的对象结构,这会变得多么混乱。有一些第三方库,如 lodash 或idx,它们有自己的功能。例如 lodash 有 _.get 方法。但是,在 JavaScript 语言本身中引入这个特性。

以下是这些新功能的工作原理:

// to get the car model
const model = car?.model ?? "default model"; // to get the manufacturer street
const street = car?.manufacturer?.address?.street ?? "default street"; // to check if the car manufacturer is from the USA
const isManufacturerFromUSA = () => {
if (car?.manufacturer?.address?.state === "USA") {
console.log("true");
}
};

目前在 Stage 3 阶段。

以上就是基于JavaScript实现条件表达式的一些分享,希望对你能有所帮助~

点击关注,第一时间了解华为云新鲜技术~

JavaScript实现:如何写出漂亮的条件表达式的更多相关文章

  1. (转)Python新手写出漂亮的爬虫代码1——从html获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78156605 Python新手写出漂亮的爬虫代码1初到大数据学习圈子的同学可能对爬虫都有 ...

  2. (转)Python新手写出漂亮的爬虫代码2——从json获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78592943 Python新手写出漂亮的爬虫代码2——从json获取信息好久没有写关于爬 ...

  3. JavaScrip条件表达式优化

    目录 1,前言 2,多条件if语句优化 3,参数默认值 4,Switch语句优化 1,前言 今早看了一篇文章<JavaScrip实现:如何写出漂亮的条件表达式>,原创于:华为云开发者社区, ...

  4. 前端开发:如何写一手漂亮的 Vue

    前几日听到一句生猛与激励并存,可怕与尴尬同在,最无奈也无解的话:"90后,你的中年危机已经杀到".这令我很受触动.显然,这有些夸张了,但就目前这日复一日的庸碌下去,眨眼的功夫,那情 ...

  5. 如何写出规范的JavaScript代码

    作为一名开发人员(WEB前端JavaScript开发),不规范的开发不仅使日后代码维护变的困难,同时也不利于团队的合作,通常还会带来代码安全以及执行效率上的问题.本人在开发工作中就曾与不按规范来开发的 ...

  6. 如何写出优雅兼备可读性的javascript代码

    即或是最简单的需求,不同的程序员也会写出不一样的代码: 需求:充值程序过虑不符合条件的充值金额,即只能充入100.200.500.1000金额,其它过虑: 1.菜鸟程序员可能会这样写,虽然可读性强,代 ...

  7. 用6个字符写出任意的Javascript代码

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用6个字符写出任意的Javascript代码.

  8. [label][翻译][JavaScript-Translation]七个步骤让你写出更好的JavaScript代码

    7 steps to better JavaScript 原文链接: http://www.creativebloq.com/netmag/7-steps-better-javascript-5141 ...

  9. 如何写出优雅的JavaScript代码 ? && 注释

    如何写出优雅的JavaScript代码 ? 之前总结过一篇<如何写出优雅的css代码?>, 但是前一段时间发现自己的js代码写的真的很任性,没有任何的优雅可言,于是这里总结以下写js时应当 ...

  10. 请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框。程序可以判断出用

    请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框.程序可以判断出用 户点击的是“确认”还是“取消”. 解答: <HTML> <HEAD> <TI ...

随机推荐

  1. OpenTiny Vue 支持 Vue2.7 啦!

    你好,我是 Kagol. 前言 上个月发布了一篇 Vue2 升级 Vue3 的文章. 少年,该升级 Vue3 了! 里面提到使用了 ElementUI 的 Vue2 项目,可以通过 TinyVue 和 ...

  2. Django admin 注册自己的路由

    通过 admin.py 在 Django 后台注册自己的路由(对应自己的视图) 要在一个 app 里面的 admin.py 添加如下代码 # django2\apps\business\admin.p ...

  3. VRRP相关简述

    VRRP 诞生原因 单网关,出问题时,旗下所有主机无法通信. 多网关,容易产生网关冲突. 而,VRRP能够在不改变组网的情况下,将多台路由器虚拟成一个虚拟路由器,通过配置虚拟路由器的IP地址为默认网关 ...

  4. [vue]精宏技术部试用期学习笔记 III

    精宏技术部试用期学习笔记(vue) 父子通信 什么是通信 / 为什么要通信 通信即在不同组件之间传输数据 当在 复用组件 时,需要传递不同数据达成不同的表现效果 能够根据其他组件的行动,响应式 的做出 ...

  5. Bug的解决

    关于使用Pandas的read_csv读取CSV文件. 用了三台Mac,在有header,同时有英文字符和中文字符的情况下,使用诸如datafile.loc[0:1 'column的名称']的方式无法 ...

  6. Webpack相关知识点

    webpack的优点 webpack从配置的入口出发,可以打包所有前端资源,同时可以配置多种loader来处理不同类型文件的转换,并且可以配置plugin来扩展模块打包流程,满足更多构建中特殊的需求, ...

  7. [NOIP 考前备战] 线段树刷题

    备战线段树 T1 AcWing .1275. 最大数 查询最大值 + 单点修改 #include <bits/stdc++.h> #define int long long using n ...

  8. Mysql数据库查询之模糊查询

    一.什么是模糊查询模糊查询是根据一定的模式匹配规则,查找与指定条件相似或相符的数据.二.模糊查询实操通配符查询1.% 表示任意0个或多个字符形式一: select 查询字段 from 表名 where ...

  9. Windows之——pid为4的system进程占用80端口的解决办法

    因为Apache无法启动的原因,用netstat命令查看了一下80端口是否被占用了,如下 C:\Users\Maple>netstat -ano | findstr 0.0.0.0:80 TCP ...

  10. Vue打包发布

    打包发布 目标:明确打包的作用 说明:vue脚手架只是开发过程中,协助开发的工具,当真正开发完了,脚手架不参与上线 打包的作用: 将多个文件压缩合并成一个文件 语法降级 less sass ts 语法 ...