
去结构化是清理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);
}
}
这可以说是比较干净的,因为我们是直接引用参数属性,skip 和path ,而不是通过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 。
总结
解构语法一开始可能看起来很奇怪,但你很快就会习惯它,它是一种使代码更干净、更可读的整洁的小方法。