JavaScript 中的模式匹配?

Pattern matching in JavaScript?

我需要在 JavaScript 中创建一个变量并根据条件为其分配值。这有效但感觉有点冗长:

  const color = (() => {
    switch (type) {
      case "primary":
        return CONSTANTS.colors.primary;
      case "secondary":
        return CONSTANTS.colors.secondary;
      case "tertiary":
        return CONSTANTS.colors.tertiary;
      case "positive":
        return CONSTANTS.colors.positive;
      case "negative":
        return CONSTANTS.colors.negative;
      case "disabled":
        return CONSTANTS.colors.disabled;
      default:
        throw new Error("A backgroundColor condition was missed");
    }
  })();

我正在尝试做的是 "pattern matching" 吗?我读到 JavaScript 确实有这个功能,但我不太确定它是什么。

上面的代码有没有更简洁的写法?我可以有很多 if 语句,但这感觉更混乱并且要求变量是 let 而不是 const

let color:
if (type === "primary") {
    color = CONSTANTS.colors.primary;
} else if(type === "secondary") {
    color = CONSTANTS.colors.secondary;
} else if(type === "tertiary") {
    color = CONSTANTS.colors.tertiary;
} else if(type === "secondary") {
    color = CONSTANTS.colors.secondary;
} else if(type === "positive") {
    color = CONSTANTS.colors.positive;
} else if(type === "negative") {
    color = CONSTANTS.colors.negative;
} else if(type === "disabled") {
    color = CONSTANTS.colors.disabled;
}

解决您问题的最简单方法是检查对象 CONSTANTS.colors 中是否定义了 type。如果你想通过变量访问一个属性,你需要使用括号注解。括号内的所有内容都被评估为表达式(因此 type 是一个变量,'type' 是字符串值)。因此,object.type returns 与 object['type'].

的值相同
let color = null;
if (typeof CONSTANTS.colors[type] !== 'undefined') {
   color = CONSTANTS.colors[type];
} else {
   throw new Error('A backgroundColor condition was missed');
}
console.log(color);

您也可以先检查对象中是否定义了键 Object.keys()includes():

let color = null;
if (Object.keys(CONSTANTS.colors).includes(type)) {
    color = CONSTANTS.colors[type];
} else {
   throw new Error('A backgroundColor condition was missed');
}
console.log(color);

如果你想支持 IE11,你cannot use .includes()。使用 .indexOf(type) !== -1 而不是 .includes(type).

您正在寻找property accessor

color = CONSTANTS.colors[type];

模式匹配通常是指匹配传递给函数的参数:测试它们是否匹配特定的 "pattern"。例如,模式匹配可能允许您编写一个函数,该函数在 "two different ways" 中接受一个整数参数,一个传入的参数是 0,另一个传入的参数不是 0 ("otherwise" 案例)。 Switch 语句有点类似于这种类型的分支逻辑,但与 Haskell 等纯函数式语言不同,并且对您的目标没有多大帮助。

换成这样怎么样?

const myColor = CONSTANTS["colors"][type];
if(typeof myColor !== 'undefined') {
    color = myColor;
} else {
   throw new Error("A backgroundColor condition was missed");
}

您的代码的简单替换是

const color = (() => {
    const color = CONSTANTS.colors[type];
    if (!color) {
        throw new Error("A backgroundColor condition was missed");
    }
    return color;
  }
  })();

不,那不是模式匹配。

我认为引入一个保存颜色值的枚举是明智的。

var ColorType = {
        Primary: "primary",
        Secondary: "secondary",
        Tertiary: "tertiary,
        ...
};

然后你可以在 switch case 中使用这个枚举,你将避免拼写错误和直接引用字符串。 我认为这将使代码不那么冗长且不易出错。

您可以使用 属性 名称作为方括号中的字符串来访问对象的 属性。

(此示例不包括您在 switch 语句中使用的错误捕获,但您可以添加它。)

const CONSTANTS = {
  colors: {
    primary: "blue",
    secondary: "yellow"
  }
} 

function getColor(myPropName){
  // Pass dynamic property names like this
  return CONSTANTS.colors[myPropName];
}

console.log(getColor("secondary"));