[译]大哥你JavaScript可能不太需要switch

1,023 阅读2分钟

译原文: www.valentinog.com/blog/switch…

作者:Valentino

译:黄梵高

无"switch" 不欢

Java的大佬非常喜欢switch,JavaScript开发人员也是如此。老实说,我们的开发人员很懒惰,对于像我这样缺乏创造力的人来说,很容易坚持现状。

switch很方便:给定一个表达式,我们可以检查它是否与一堆case子句中的其他项匹配。考虑以下示例:

const name = "Juliana";

switch (name) {
  case "Juliana":
    console.log("She's Juliana");
    break;
  case "Tom":
    console.log("She's not Juliana");
    break;
}

当名称为Juliana时,我们将打印一条消息,并立即通过退出break。当switch在函数内部时break,只要您从每个子句返回,就可以省略。

当没有匹配项时,您还可以具有默认分支:

const name = "Kris";

switch (name) {
  case "Juliana":
    console.log("She's Juliana");
    break;
  case "Tom":
    console.log("She's not Juliana");
    break;
  default:
    console.log("Sorry, no match");
}

switch 在 Redux reducers 当中大量使用,通过 Redux Toolkit 简化了样板,避免了一大坨 if 语句

const LOGIN_SUCCESS = "LOGIN_SUCCESS";
const LOGIN_FAILED = "LOGIN_FAILED";

const authState = {
  token: "",
  error: "",
};

function authReducer(state = authState, action) {
  switch (action.type) {
    case LOGIN_SUCCESS:
      return { ...state, token: action.payload };
    case LOGIN_FAILED:
      return { ...state, error: action.payload };
    default:
      return state;
  }
}

还不错,没什么问题,但是我们还能有更好的选择么?

借鉴Python

来自Telmo的这条推文引起了我的注意。他展示了两种“切换”样式,其中一种非常接近Python中的相似模式

Python没有switch,它可以教我们一个更好的替代方法,以取代我们钟爱的混乱switch。首先让我们将代码从JavaScript移植到Python:

LOGIN_SUCCESS = "LOGIN_SUCCESS"
LOGIN_FAILED = "LOGIN_FAILED"

auth_state = {"token": "", "error": ""}


def auth_reducer(state=auth_state, action={}):
    mapping = {
        LOGIN_SUCCESS: {**state, "token": action["payload"]},
        LOGIN_FAILED: {**state, "error": action["payload"]},
    }

return mapping.get(action["type"], state)

在Python中,我们可以将switch使用字典进行模拟。这种default情况由dict.get()替代默认值。

当访问一个不存在当key,python可能会出现一个KeyError

>>> my_dict = {
    "name": "John", 
    "city": "Rome", 
    "age": 44
    }

>>> my_dict["not_here"]

# Output: KeyError: 'not_here'

这个.get()方法是直接通过key值访问的一种更安全的替代方法,因为它不会导致报错,并可以为不存在的键指定默认值:

>>> my_dict = {
    "name": "John", 
    "city": "Rome", 
    "age": 44
    }

>>> my_dict.get("not_here", "not found")

# Output: 'not found'

因此,Python中的这一行:

# omit
    return mapping.get(action["type"], state)

在JavaScript中等效于:

function authReducer(state = authState, action) {
// omit
    default:
      return state
}

让我们将相同的Python风格的代码使用在JavaScript中。

替代switch

如果我们想要摆脱switch,我们可以这么做:

function authReducer(state = authState, action) {
  const mapping = {
    [LOGIN_SUCCESS]: { ...state, token: action.payload },
    [LOGIN_FAILED]: { ...state, error: action.payload }
  };

  return mapping[action.type] || state;
}

看起来清爽多了,这么棒的反馈可能要感谢现代JavaScript,对象计算属性值在ES2015中的出现,同时要感谢展开语法的出现,让...state可以直接展开,简化写法,更加清晰。

你喜欢这种处理方式吗?当然这和switch相比是有一定局限的,至少对于一个reducer来讲,这可能是更简洁的技巧吧。

感谢阅读!