如何使用 switch 语句创建函数 javascript

how to create a function with switch statement javascript

我目前正在学习JS,我需要用switch语句做下面的练习。

function colorMix (color1, color2){
  if ((color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red')){
    return 'violet';
  } else if ((color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red')){
    return 'orange';
  } else if ((color1 === 'blue' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'blue')){
    return 'green';
  } else {
    return 'need to mix two diferent colours'
  }
}

 let myColor = colorMix('blue', 'blue');
  console.log(`The color created is: ${ myColor}`);

这是我目前得到的结果,但它不起作用:

let color1 = '';
let color2 = '';

let firstColour = ((color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red'))
let secondColour = ((color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red'))
let thirdColour = ((color1 === 'blue' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'blue'))

function colorMix (color1, color2){
switch (color1, color2){
  case 'firstColour':
    return 'violet';
    break;
  case 'secondColour':
    return 'orange';
    break;
  case 'thirdColour':
    return 'green';
  default:
    return 'error';
  }
}

let myColour = colorMix('red', 'blue');
console.log(`Colour created is ${myColour}`)

我不知道如何让 switch 语句识别我介绍的颜色。有什么想法吗?谢谢!!!

与其使用 switch 语句进行过多比较,您可以获取数组中的所有颜色并对它们进行排序,然后使用规范化顺序进行检查。

function colorMix(...colors) {
    colors.sort();
    if (color[0] === 'blue' && color[1] === 'red') return 'violet';
    if (color[0] === 'red' && color[1] === 'yellow') return 'orange';
    if (color[0] === 'blue' && color[1] === 'yellow') return 'green';
    return 'need to mix two diferent colours';
}

Set

的不同方法
function colorMix(...colors) {
    const
        mixedColors = {
            violet: new Set(['blue', 'red']),
            orange: new Set(['red', 'yellow'])
            green: new Set(['blue', 'yellow'])
        };

    return Object.keys(mixedColors).find(c => colors.every(Set.prototype.has, mixedColors[c]))
        || 'need to mix two diferent colours';
}

最后一个没有状态,只有一个访问器

function colorMix(...colors) {
    const mixed = {
        blue: { red: 'violet', yellow: 'green' },
        red: { yellow: 'orange' }
    }
    colors.sort();
    return mixed[colors[0]]?.[colors[1]] ||'need to mix two diferent colours';
}

您可以通过将颜色组合成一个键并打开该键来实现:

function colorMix (color1, color2){
    const key = color1 < color2 ? color1 + " \t " + color2 : color2 + " \t " + color1;
    switch (key) {
        case "blue \t red":
            return "violet";
        case "red \t yellow");
            return "orange";
        case "blue \t yellow";
            return "green";
        default:
            return return "need to mix two diferent colours";
    }
}

假设颜色名称中没有 space/tab/space。

之所以可行,是因为我们使用的是可以组合成单个键的字符串。如果我们不这样做,或者表达式更复杂,那么虽然 可能 switch 来做到这一点,但没有充分的理由,你基本上会写与 if/else if 链相同的东西(因为在 JavaScript 中,这就是 switch 的全部——不像其他一些具有类似语法的语言),并且结果 真的 让阅读代码的任何人都感到惊讶。

为了完整起见,这里是一般情况:

// DON'T DO THIS
switch (true) {
    case (color1 === 'red' && color2 === 'blue') || (color1 === 'blue' && color2 === 'red'):
        return 'violet';
    case (color1 === 'red' && color2 === 'yellow') || (color1 === 'yellow' && color2 === 'red'):
        return 'orange';
    // ...
}

之所以可行,是因为 case 标签是 JavaScript 中的表达式,它们按顺序测试(default 除外),使用第一个匹配项。

但是,再次强调,不要那样做。 :-D

您也可以考虑查找 table:

// Creates a key for the two colors, where the colors are always
// in lexicographical order (so we don't have to worry about the
// argument order)
const colorKey = (color1, color2) => color1 < color2 ? color1 + "\t" + color2 : color2 + "\t" + color1;

const colorMix = new Map([
    [colorKey("blue", "red"), "violet"],
    [colorKey("red", "yellow"), "orange"],
    [colorKey("blue", "yellow"), "green"],
]);

// ...

function colorMix (color1, color2){
    const color = colorMix.get(colorKey(color1, color2));
    return color ?? "need to mix two diferent colours";
}

这里我使用按位添加颜色,所以无论顺序如何,它们总是会生成一个唯一的 ID,我使用开关检查颜色 ID,这将是两种颜色的 ID 之和。

function getColorIndex(color1, color2) {
    const colors = {
        "red": 1,
        "blue": 2,
        "yellow": 4 // next will be the double (n * 2) e.g: "violet": 8
    }

    return color1 !== color2 ? colors[color1] | colors[color2] : -1;
}

function colorMix (color1, color2) {
    switch (getColorIndex(color1, color2)) {
        case 3: // red + blue (1 + 2 === 3)
            return "violet";
        case 5: // red + yellow (1 + 4 === 5)
            return "orange";
        case 6: // blue + yellow (2 + 4 === 6)
            return "green";
        case -1: // getColorIndex will return -1 if colors are equal
            return "need to mix two diferent colours";
        default:
            return `Unrecognized colors: ${color1} + ${color2}`;
    }
}

let myColor = colorMix('blue', 'blue');
console.log(`The color created is: ${ myColor}`);

myColor = colorMix('omg', 'idk');
console.log(`The color created is: ${ myColor}`);

myColor = colorMix('red', 'yellow');
console.log(`The color created is: ${ myColor}`);

表达式 (color1, color2) 的计算结果为 color2,因为这里的逗号是 operator。所以这对 switch 语句没有用。

使其工作的一种方法是将颜色 strings 转换为颜色 numbers,这样原理颜色 (红色、黄色和蓝色)是 2 的幂。如果将它们相加(或更好地进行“或”运算),则找到其他颜色编号。

这是如何做到的:

const colorNames = ["none", "red", "yellow", "orange", "blue", "violet", "green", "black"];
const colorNums = Object.fromEntries(colorNames.map((name, i) => [name, i]));

const colorMix = (color1, color2) => colorNames[colorNums[color1] | colorNums[color2]];

console.log(colorMix("blue", "red")); // violet
// Order does not matter
console.log(colorMix("red", "blue")); // violet
// Mixing a color with itself does not change it
console.log(colorMix("orange", "orange")); // orange
// Can mix an already mixed color again
console.log(colorMix("violet", "yellow")); // black

说明

const colorNames = ["none", "red", "yellow", "orange", "blue", "violet", "green", "black"];

这里我们创建了一个颜色名称数组。该数组中名称出现的 index 是其唯一标识符。主要颜色在指数上,指数是 2 的幂:1、2 和 4。如果我们将指数写成二进制数,则上面的数组如下所示:

index in binary color name
000 none
001 red
010 yellow
011 orange
100 blue
101 violet
110 green
111 black

这个数组可以用来给出索引对应的颜色名称。请注意“橙色”(011) 如何组合“红色”(001) 和“黄色”(010) 的二进制位,当两种混合颜色中的任何一种在二进制的相同位置具有“1”时取“1”表示。

以下语句创建反向映射(从名称到索引):

const colorNums = Object.fromEntries(colorNames.map((name, i) => [name, i]));

.map() 创建名称和索引对(上面的 table 但交换了列)。 Object.fromEntries 使用此信息创建普通对象:

{
    none: 0,
    red: 1,
    yellow: 2,
    orange: 3,
    blue: 4,
    violet: 5,
    green: 6,
    black: 7
} 

有了这两个转换对象,我们现在可以制作一个漂亮的颜色混合器函数:

const colorMix = (color1, color2) => colorNames[colorNums[color1] | colorNums[color2]];

使用 colorNums.

将两种颜色各自转换为它们的数字

这两个数字使用二元或运算符 (|) 组合。这将给出我们想要得到的颜色的数量。

最后,使用 colorNames 数组将该值转换回颜色名称。

脚本的其余部分说明了如何调用函数:

  • 参数的顺序无关紧要
  • 当两种输入颜色相同时,行为与您所做的不同:颜色原封不动地返回,原因是将颜色与自身混合不会改变颜色。
  • 已经混合的颜色可以再次混合(这当然是对现实的简化,混合颜色受到与另一种颜色混合的的影响。相对金额影响结果)。