网络编程
位置:首页>> 网络编程>> JavaScript>> 如何利用JavaScript编写更好的条件语句详解

如何利用JavaScript编写更好的条件语句详解

作者:cuppar  发布时间:2023-08-05 04:07:18 

标签:js,条件语句

前言

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

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

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

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

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

它工作得很好,但是代码很长并且维护困难。如果不使用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 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'

现在,我们有:

1 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,代码没有嵌套语句了。这种技术在我们有很多条件并且当任何特定条件不匹配时,我们想停止进一步处理的时候特别有用。

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

3. 用对象字面量或Map替代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 允许保存键值对,是自从ES2015以来可以使用的对象类型。

对于上面的例子,相同的功能也能用数组方法 Array.filte 来实现。


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 1
if (!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) 时会得到一个错误:不能从 undefined 或 null 解构属性 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 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
}

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 阶段,让我们等待它获得批准,然后我们就能无处不在地看到这难以置信的语法的使用。

总结

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

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

0
投稿

猜你喜欢

  • 返回首页的链接地址,有三种方法:1、一般方法是,直接写对应的域名地址,<a href="http://www.zfnn.co
  • 如何用表单的方式推送请求的信息?具体见下:<html><head><title>答复用户信息 
  • 一.权限表mysql数据库中的3个权限表:user 、db、 host权限表的存取过程是:1)先从user表中的host、 user、 pa
  • 相信没有人不知道 Firebug 是什么东西,但有时候我们糟糕的代码不想让同行轻松的使用 F12 就能一览无遗。那么怎么办呢?这里有个猥琐的
  • 一、 网页设计中的对比原则一件网页设计作品由许多元素构成,它们的重要性各不相同,其中一些元素的重要性要高于其它元素。一些相互关联,而另一些则
  • 内容摘要:我们在浏览一些文章的时候,当鼠标选中一些文字的时候,就出现了一些隐藏的字符,平常是看不到的。这些干扰码一般有两种,一是随机无意义的
  • 在这个星期Doug Bowman离开谷歌的Twitter引发了很多激烈的讨论.在残酷的诚实邮件中,Doug Bowman援引谷歌”限制性的数
  • 一、增强的可扩展性 Oracle9i Real Application Clusters是Oracle的下一代并行服务器系列产品。Oracl
  • IE测试通过,FF有点小BUGCls_Leibie.asp代码如下:<% '数据库字段为类属性,添加、删除、修改、操
  • 第一次用Python写这种比较实用且好玩的东西,权当练手吧游戏说明:* P键控制“暂停/开始”* 方向键控制贪吃蛇的方向源代码如下:from
  • 如果你正在运行使用MySQL的Web应用程序,那么你把密码或者其他敏感信息保存在应用程序里的机会就很大。保护这些数据免受黑客或者窥探者的获取
  • 本次薯片会讨论了关于分类与类型的问题。怎么找一个item?页面导航一般分类为主,在具体的分类展示下选择类型:典型例子:炫铃(QQ客户端)当只
  • 当然这应该属于正常过滤手法,而还有一种过滤HTML标签的最终极手法,则是将一对尖括号及尖括号中的所有字符均替换不显示,该方法对于内容中必须描
  • EXISTS该函数返回集合中第一个元素的索引,如果集合为空,返回NULLNULLNULLCollection.EXISTS(index)CO
  • 一 描述720. 词典中最长的单词 - 力扣(LeetCode) (leetcode-cn.com)给出一个字符串数组 words
  • 代码如下:---在仓储管理中经常会碰到的一个问题 一、关于LIFO与FIFO的简单说明 ---FIFO: First in, First o
  • 这篇文章阐述的是一种函数式编程(functional-programming)设计模式,我称之为惰性函数定义(Lazy Function D
  • Firefox 的 Jetpack 可以让我们很轻松地创建 Firefox 插件,仅通过已掌握的前端技能(HTML/CSS/JS),估计让人
  • 过程名:ManualPagination作 用:采用手动分页方式显示文章具体的内容参 数:ArticleID,strContentSub&n
  • 这个收藏本站、设为首页代码相信每个网站都会用到,这么常用的代码,网络上流行的一般是很多年前的代码版本,只有兼容IE,对其它浏览器没有考虑,下
手机版 网络编程 asp之家 www.aspxhome.com