文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

浅谈JS如何写出漂亮的条件表达式

2024-04-02 19:55

关注

多条件语句

多条件语句使用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'

现在,我们有:


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实现条件表达式的一些分享,希望对你能有所帮助~

以上就是浅谈JS如何写出漂亮的条件表达式的详细内容,更多关于JS如何写出漂亮的条件表达式的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯