JavaScript 编写优雅条件表达式的 6 种技巧

作者:代码拾荒时间:2026-10-24 11:26:34浏览:456

本文深入探讨如何在 JavaScript 中编写简洁、易维护的条件表达式。通过 Array.includes 简化多条件判断,利用解构与默认参数处理对象属性,采用早期返回降低嵌套层级,以及使用 Map 替代冗长的 Switch 语句。此外,还介绍了 Array.every/some 进行集合校验,以及可选链和 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

此种写法在条件较少时看似可行,例如仅涉及两种动物;但若需判断更多条件(如更多动物),继续扩展判断逻辑将导致代码难以维护且逻辑不清。

解决方案

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

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

作者最新文章