用去结构化清理你的代码(附实例)

161 阅读3分钟

去结构化是清理JavaScript代码的一种很好的方式。在这篇文章中,我们将通过很多不同的领域,来了解去结构化对代码的可读性的帮助。

函数参数

当一个函数参数是一个对象而不是一个基元时,可以使用重构来将该对象分解为函数引用的部分。下面的代码是没有任何析构的:

async function logData(options) {
  if (!options.skip) {
    const response = await fetch(options.path);
    const data = await response.json();
    console.log(data);
  }
}

通过对options 参数进行解构,可以将其重构为下面的代码:

async function logData({ skip, path }) {
  if (!skip) {
    const response = await fetch(path);
    const data = await response.json();
    console.log(data);
  }
}

这可以说是比较干净的,因为我们是直接引用参数属性,skippath ,而不是通过options 参数名称。

这种方法的一个真正的好处是,我们可以将默认值应用于去结构化的属性。如果没有去结构化,我们会有一些像这样的东西:

async function logData(options) {
  const path = options.path || "https://swapi.co/api/people/1";
  if (!options.skip) {
    const response = await fetch(path);
    const data = await response.json();
    console.log(data);
  }
}

......但有了结构化,它就更干净了:

async function logData({ skip, path = "https://swapi.co/api/people/1" }) {
  if (!skip) {
    const response = await fetch(path);
    const data = await response.json();
    console.log(data);
  }
}

除了节省一行代码外,在参数声明的旁边有参数的默认值可以帮助我们更容易地理解参数。

这种方法在React函数组件中对组件的props很有用:

export const CountDown = ({ start = 10 }) => {
  const [count, setCount] = useState(start);
  ...
};

start 是上例中 组件中的一个道具。CountDown

一个休息参数可以用来收集还没有被解构的属性。这对于在React组件中通过道具传递给较低级别的元素很有用:

const Field = ({ id, label, value, type = "text", onChange, ...rest }) => {
  return (
    <div>
      <label for={id}>{label}</label>
      <input type={type} id={id} value={value} onChange={onChange} {...rest} />
    </div>
  );
};

解构也可以应用于本身是对象的参数属性。下面是一个没有去结构化的例子:

async function sendEmail(config) {
  const response = await fetch(config.api.path, {
    method: "post",
    body: JSON.stringify({
      emailAddress: config.contact.emailAddress,
      template: config.template
    })
  });
  return response.ok;
}

... 可以重构为以下内容:

async function sendEmail({
  api: { path },
  contact: { emailAddress },
  template
}) {
  const response = await fetch(path, {
    method: "post",
    body: JSON.stringify({
      emailAddress,
      template
    })
  });
  return response.ok;
}

...并且带有一些默认值:

async function sendEmail({
  api: { path = "https://some-email-server" },
  contact: { emailAddress },
  template = "standard"
}) {
  const response = await fetch(path, {
    method: "post",
    body: JSON.stringify({
      emailAddress,
      template
    })
  });
  return response.ok;
}

我们可以使用TypeScript来对去结构化的元素进行强类型化,如下所示:

async function logData({
  skip = false,
  path = "https://swapi.co/api/people/1"
}: {
  skip?: boolean,
  path?: string
}) {
  if (!skip) {
    const response = await fetch(path);
    const data = await response.json();
    console.log(data);
  }
}

... 或者我们可以从函数中提取类型:

type LogDataOptions = {
  skip?: boolean,
  path?: string
};
async function logData({
  skip = false,
  path = "https://swapi.co/api/people/1"
}: LogDataOptions) {
  if (!skip) {
    const response = await fetch(path);
    const data = await response.json();
    console.log(data);
  }
}

函数调用结果

对一个函数的调用结果可以是去结构化的。因此,如果没有去结构化,我们可能会有这样的东西:

const character = await getCharacter(1);
console.log(character.name);

...通过去结构化可以重构为以下内容:

const { name } = await getCharacter(1);
console.log(name);

默认值可以以与函数参数相同的方式应用:

const { name = "Unknown" } = await getCharacter(1);
console.log(name);

去结构化的元素也可以用TypeScript进行强类型化:

const { name = "Unknown" }: { name: string } = await getCharacter(1);
console.log(name);

...或者使用可重用的类型:

type Character = {
  name: string;
  height: string;
  gender: "male" | "female";
  ...
}
...
const { name = "Unknown" }: Character = await getCharacter(1);
console.log(name);

去结构化的项目可以按以下方式重命名:

const { name: characterName } = await getCharacter(1);
console.log(characterName);

...并使用TypeScript类型注解:

const { name: characterName }: { name: string } = await getCharacter(1);

请注意,该类型代表了它的属性被重命名之前的数据。

数组也可以被去结构化。事实上,这被用来消耗React钩子。

count 是由 钩子返回的第一个数组项, 是第二个。useState setCount

在解构过程中,数组项也可以被跳过:

const [, , z] = getPoint();

在上面的例子中,我们跳过前两个数组项,把第三个项分配给z

总结

解构语法一开始可能看起来很奇怪,但你很快就会习惯它,它是一种使代码更干净、更可读的整洁的小方法。