作者:cuppar

https://www.zcfy.cc/article/tips-to-write-better-conditionals-in-javascript-dev-community

在任何编程语言中,代码需要根据不同的条件在给定的输入中做不同的决定和执行相应的动作。

例如,在一个游戏中,如果玩家生命点为0,游戏结束。在天气应用中,如果在早上被查看,显示一个日出图片,如果是晚上,则显示星星和月亮。在这篇文章中,我们将探索JavaScript中所谓的条件语句如何工作。

如果你使用JavaScript工作,你将写很多包含条件调用的代码。条件调用可能初学很简单,但是还有比写一对对if/else更多的东西。这里有些编写更好更清晰的条件代码的有用提示。

  1. 数组方法 Array.includes

  2. 提前退出 / 提前返回

  3. 用对象字面量或Map替代Switch语句

  4. 默认参数和解构

  5. 用 Array.every & Array.some 匹配全部/部分内容

  6. 使用可选链和空值合并

1. 数组方法 Array.includes

使用 Array.includes 进行多条件选择

例如:

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

上面的代码看起来很好因为我们只检查了两个动物。然而,我们不确定用户输入。如果我们要检查任何其他动物呢?如果我们通过添加更多“或”语句来扩展,代码将变得难以维护和不清晰。

解决方案:

我们可以通过使用 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

这里,我们创建来一个动物数组,所以条件语句可以和代码的其余部分抽象分离出来。现在,如果我们想要检查任何其他动物,我们只需要添加一个新的数组项。

我们也能在这个函数作用域外部使用这个动物数组变量来在代码中的其他任意地方重用它。这是一个编写更清晰、易理解和维护的代码的方法,不是吗?

2. 提前退出 / 提前返回

这是一个精简你的代码的非常酷的技巧。我记得当我开始专业工作时,我在第一天学习使用提前退出来编写条件。

让我们在之前的例子上添加更多的条件。用包含确定属性的对象替代简单字符串的动物。

现在的需求是:

  • 如果没有动物,抛出一个异常

  • 打印动物类型

  • 打印动物名字

  • 打印动物性别

const printAnimalDetails = animal => {let result; // declare a variable to store the final value// condition 1: check if animal has a valueif (animal) {// condition 2: check if animal has a type propertyif (animal.type) {// condition 3: check if animal has a name propertyif (animal.name) {// condition 4: check if animal has a gender propertyif (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'

你觉得上面的代码怎么样?

它工作得很好,但是代码很长并且维护困难。如果不使用lint工具,找出闭合花括号在哪都会浪费很多时间。???? 想象如果代码有更复杂的逻辑会怎么样?大量的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 presentif (vegetable) {// condition 2: must be one of the item from the listif (vegetables.includes(vegetable)) {console.log(I like ${vegetable});// condition 3: must be large quantityif (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'

现在,我们有:

  • 1 if/else 语句过滤非法条件

  • 3 级嵌套if语句 (条件 1, 2, & 3)

一个普遍遵循的规则是:在非法条件匹配时提前退出。

function printVegetablesWithQuantity(vegetable, quantity) {const vegetables = ['potato', 'cabbage', 'cauliflower', 'asparagus'];// condition 1: throw error earlyif (!vegetable) throw new Error('No vegetable from the list!');// condition 2: must be in the listif (vegetables.includes(vegetable)) {console.log(I like ${vegetable});// condition 3: must be a large quantityif (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 earlyif (!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 quantityif (quantity >= 10) {console.log('I have bought a large quantity');}
}

通过倒置条件2,代码没有嵌套语句了。这种技术在我们有很多条件并且当任何特定条件不匹配时,我们想停止进一步处理的时候特别有用。

所以,总是关注更少的嵌套和提前返回,但也不要过度地使用。

3. 用对象字面量或Map替代Switch语句

让我们来看看下面的例子,我们想要基于颜色打印水果:

function printFruits(color) {// use switch case to find fruits by colorswitch (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 colorconst fruitColor = {red: ['apple', 'strawberry'],yellow: ['banana', 'pineapple'],purple: ['grape', 'plum']};function printFruits(color) {return fruitColor[color] || [];
}

另外,你也能用 Map 来实现相同的功能:

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

Map 允许保存键值对,是自从ES2015以来可以使用的对象类型。

对于上面的例子,相同的功能也能用数组方法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);
}

4. 默认参数和解构

当使用 JavaScript 工作时,我们总是需要检查 null/undefined 值并赋默认值,否则可能编译失败。

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

如果 vegetable 是一个对象呢?我们能赋一个默认参数吗?

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

在上面的例子中,如果vegetable 存在,我们想要打印 vegetable name, 否则打印"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 } 解构参数,然后我们就能在代码中使用 name 作为变量,而不是 vegetable.name

我们还赋了一个空对象 {} 作为默认值,因为当执行 printVegetableName(undefined) 时会得到一个错误:不能从 undefinednull 解构属性 name ,因为在 undefined 中没有 name 属性。

5. 用 Array.every & Array.some 匹配全部/部分内容

我们能使用数组方法减少代码行。查看下面的代码,我们想要检查是否所有的水果都是红色的:

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

6. 使用可选链和空值合并

这有两个为编写更清晰的条件语句而即将成为 JavaScript 增强的功能。当写这篇文章时,它们还没有被完全支持,你需要使用 Babel 来编译。

可选链允许我们没有明确检查中间节点是否存在地处理 tree-like 结构,空值合并和可选链组合起来工作得很好,以确保为不存在的值赋一个默认值。

这有一个例子:

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

这看起来很美观并容易维护。它已经到 TC39 stage 3 阶段,让我们等待它获得批准,然后我们就能无处不在地看到这难以置信的语法的使用。

总结

让我们为了编写更清晰、易维护的代码,学习并尝试新的技巧和技术,因为在几个月后,长长的条件看起来像搬石头砸自己的脚。????

若此文有用,何不素质三连❤️

使用 JavaScript 编写更好的条件语句相关推荐

  1. Web前端开发笔记——第四章 JavaScript程序设计 第四节 条件语句和循环语句

    目录 一.if条件语句 二.while循环语句 (一)while()语句 (二)do--while语句 三.for循环语句 四.switch语句 五.break语句和continue语句 一.if条件 ...

  2. 【前端】【JavaScript案例】之用条件语句实现输入年份判断生肖

    已知,公元后生肖年的计算方法: 年份除以12,取所得余数,对照下表查看生肖: 0猴,1鸡,2狗,3猪,4鼠,5牛,6虎,7兔,8龙,9蛇,10马,11羊 方法一 else if : var year1 ...

  3. 【TypeScript入门】TypeScript入门篇——条件语句

    条件语句是用来判断给定的条件是否满足(表达式值是否为0),并根据判断的结果(真或假)决定执行的语句,选择结构就是用条件语句来实现的.条件语句可以给定一个判断条件,并在程序执行过程中判断该条件是否成立, ...

  4. python和循环语句_Python 小白零基础入门 -- 条件语句和循环语句

    Python 小白零基础入门 -- 条件语句和循环语句 点击上方 "Python 读数", 选择 "星标" 公众号 重磅干货, 第一时间送达 Python 零基 ...

  5. 5个技巧让你更好的编写 JavaScript(ES6) 中条件语句

    使用 JavaScript 时,我们经常需要处理很多条件语句,这里分享5个小技巧,可以让你编写更好/更清晰的条件语句. 1.使用 Array.includes 来处理多个条件 我们来看看下面的例子: ...

  6. 5个小技巧让你写出更好的 JavaScript 条件语句

    在使用 JavaScript 时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净.漂亮的条件语句. 1.使用 Array.includes 来处理多重条件 举个栗子 : // 条件语 ...

  7. 5个小技巧让你写出更好的JavaScript 条件语句

    在使用 JavaScript 时,我们常常要写不少的条件语句.这里有五个小技巧,可以让你写出更干净.漂亮的条件语句. 使用 Array.includes 来处理多重条件 举个栗子 : // 条件语句 ...

  8. 前端 JavaScript 条件语句优化

    我们日常使用到的逻辑判断语句有 if...else....switch...case....do...while...等. 在简单场景下,我们可能对这些语法的性能没有什么感觉,但当遇到复杂的业务场景时 ...

  9. JavaScript 如何工作的: 事件循环和异步编程的崛起 + 5 个关于如何使用 async/await 编写更好的技巧...

    原文地址:How JavaScript works: Event loop and the rise of Async programming + 5 ways to better coding wi ...

最新文章

  1. UVA 315 :Network (无向图求割顶)
  2. 零基础自学python的app-编程零基础应当如何开始学习 Python?
  3. python官方推荐的三本书-一个合格的python程序员,应该从这三本书入手
  4. 使用 libpcap 实现网络转包
  5. laravel-admin 使用 wangEditor 的一些小方法
  6. C# WPF 显示图片和视频显示 EmuguCv、AForge.Net测试
  7. 【Go语言】【13】再谈GO语言的结构体
  8. Parallels Desktop 安装Win 10提示“安全启动功能防止操作系统启动”该如何操作?
  9. Ant + Jenkies +Tomcat 自动构建部署Web项目
  10. 淘宝商城事件:中小卖家缺失的互联网信任
  11. 网页英文 错位_浏览器不兼容,网页错位的简单解决方法
  12. 企业u盘系统服务器,服务器u盘装系统
  13. 友情链接模块phpcms
  14. 基于机智云物联网平台4孔插座开源
  15. 接口和继承知识点总结
  16. Spinner用法案例
  17. 2014京东校园招聘-软件开发笔试题
  18. 学习笔记 山外K60库图像解压函数原理(底层代码详解)
  19. python实现视频分割
  20. matlab粒子群加约束条件_matlab粒子群编程,等式约束如何加入

热门文章

  1. vmp版本某数后缀(10-6,js逆向)
  2. 一周总结——2020.7.5
  3. 如何选择时间序列预测模型
  4. 微信小程序商品详情页交互源码(选择商品类型切换、预览商品图片)
  5. Scrapyd参考文档
  6. 10.2 配置高级的访问控制列表
  7. 推荐一款运动蓝牙耳机,最全运动蓝牙耳机推荐
  8. 分布式服务器架构搭建和部署
  9. android自学知乎!百度、阿里、滴滴、新浪的面试心经总结,大厂面试题汇总
  10. 【积累】性能测试-响应时间的‘2-5-8’原则