循环改造
const cats = [
{ name: "Mojo", months: 84 },
{ name: "Mao-Mao", months: 34 },
{ name: "Waffles", months: 4 },
{ name: "Pickles", months: 6 },
];
const kittens = [];
//典型的 for 循环用法
for (const i = 0; i < cats.length; i++) {
if (cats[i].months < 7) {
kittens.push(cats[i].name);
}
}
console.log(kittens);
我们改造的第一步是将 if
语句中的逻辑判断提取出来,老实说提取之后笔者觉得正好符合
const isKitten = (cat) => cat.months < 7;
const kittens = [];
for (const i = 0; i < cats.length; i++) {
if (isKitten(cats[i])) {
kittens.push(cats[i].name);
}
}
这种方式一方面增加了代码的可用性,另一方面也保证了我们测试条件的可测试性,特别是当我们的逻辑判断很复杂的时候。下面我们是将属性提取也抽象出来:
const isKitten = (cat) => cat.months < 7;
const getName = (cat) => cat.name;
const kittens = [];
for (const i = 0; i < cats.length; i++) {
if (isKitten(cats[i])) {
kittens.push(getName(cats[i]));
}
}
下面我们可以用函数式中的过滤与转换函数来描述这个过程:
const isKitten = (cat) => cat.months < 7;
const getName = (cat) => cat.name;
const kittens = cats.filter(isKitten).map(getName);
到这里我们摒弃了push
函数,即移除了可变状态的介入。最后的重构即是将我们的过滤与转换过程再进行一层封装,使其成为可复用的过程:
const isKitten = (cat) => cat.months < 7;
const getName = (cat) => cat.name;
const getKittenNames = (cats) => cats.filter(isKitten).map(getName);
const cats = [
{ name: "Mojo", months: 84 },
{ name: "Mao-Mao", months: 34 },
{ name: "Waffles", months: 4 },
{ name: "Pickles", months: 6 },
];
const kittens = getKittenNames(cats);
console.log(kittens);