也许可以不用 If… Else

3,121 阅读3分钟

之前在写一个 React 项目时,我发现我用了太多的 if else,于是在重构代码的时候,我尝试删除了大量的 if else,最终发现代码变简洁了,可读性更高了。所以如果你的代码中也出现了大量的if else,说明你的代码出问题了。

在 code reviews 的时候,我会关注下面几个问题:

  • 一个函数干了几件事情,是否需要分离,让一个函数只干一件事?
  • 检查函数中的 if else,看是否可以替换它。
  • 怎么改善可读性?比如用设计模式替换if else(我最喜欢用对象映射模式)。
  • 如果必须使用 if else,那么删除 else,保留 if,并返回默认值。

接下来我会举几个例子来展示如何替代 if else

删除 else

重构前:

if (red) {
  return false;
} else if (blue) {
  return false;
} else {
  return true;
} 

重构后:

if (red || blue) {
    return false;
}
return true;

重构后的代码可以很直观的看到默认返回值,更简洁易读。

组合函数

当你发现一个函数做了很多件事情,那么用组合函数可以很好的处理它。把函数分离成多个函数,然后把它们组合起来。

举个例子:我们来创建一个可以生成包含皮毛和爪子的雌性动物的函数

import { flow } from 'lodash';

const femaleAnimalsWithFurAndClaws = flow(
  getFemales,
  getAnimalsWithFur,
  getAnimalsWithClaws,
)(animals);

代码处理成这样,我们可以很轻松的重用里面的函数(比如 getFemales)。

对象映射模式

这是我最喜欢的设计模式之一,可使用的场景也很多,不管是在前端还是后端编码中都可以用。它带来的好处就是,让代码简洁易读。每次我用这种设计模式的时候,我都觉得我的代码不是代码,而是说明书(^_^)。

来看一个简单的例子:

const colors = {
  red: false,
  blue: false,
  'default': true,
 };

const colorMapper = color => colors[color] || colors['default'];

const color = colorMapper(item.color);

它由两个部分组成,一个储存返回结果的对象和一个映射函数。

我们设置了默认值,即使在调用 colorMapper 函数的时候,没有传入参数,或者传入了错误参数,都不会报错,并返回默认值。后期维护的时候,我们也可以很轻松的新增其他的颜色。

当然我们也可以用 switch 来达到同样的效果,就我个人而言并不喜欢这种语法,还是对象映射的方式更简洁优美(^_^)。

对象映射模式 + React

用 React 写项目,才是对象映射模式大放异彩的时候。当我们渲染很多不同的组件时,我们需要在代码中写大量的条件判断。如果用对象映射模式,问题就变得简单了。看下面的例子:

首先数据看起来是这样的,每个对象都有一个 typecontent 键。

const items = [{
 type: ‘hero’,
 content: : {…},
}, {
 type: 'text',
 content: : {…},
}, {
 type: 'image_and_text',
 content: : {…},
}, {
 type: 'text',
 content: : {…},
}, {
 type: 'call_to_action',
 content: : {…},
}];

然后写一个映射函数,每个键表示一个 React 组件,每个组件都有 prop,就上面数据中的 content

const components = {
 hero: HeroComponent,
 text: TextComponent,
 image_and_text: ImageAndTextComponent,
 call_to_action: CallToActionComponent,
 'default': null,
};

const componentMapper = type => 
components[type] || components['default'];

接下来就可以在项目中用了:

import react from ‘react’;

const RenderItems = props => {
 
 const componentList = props.items((item, index) => {
   const Component = componentMapper(item.type);
   return <Component content={item.content} />
 };

 return (
  <div>
   {componentList}
  </div>
 )
};

感谢阅读!

本文翻译自Fredrik JensenIf… Else, or not!