JavaScript 中的函数式编程

不赘述函数式编程,从函数式编程的几点原则开始给大家提供一些代码风格的转换思路。

函数式编程的原则是不可变数据

这里暂时不考虑性能问题。使用不可变数据可以大大提高代码可维护性。

场景

根据一个数组生成一个新的数组。新的数组内容和之前的数组的内容一一对应

// not good
const userIdList = [];
for (let i = 0; i < users.length; i++) {
    userIdList.push(users[i].id);
}

// good
const userIdList = users.map((user) => {
    return user.id;
});

根据一个数组,生成一个新数组。新的数组内容是之前数组内容的一部分

// not good
const validUsers = [];
for (let i = 0; i < users.length; i++) {
    if (user.isValid) {
        validUsers.push(user);
    }
}

// good
const validusers = users.filter((user) => {
    return user.isValid;
});

根据一个数组,生成一个新的数组。新数组是旧数组中的数据的重组

// not good
const children = [];
for (let i = 0; i < users.length; i++) {
    children.push(...user.children);
}

// not good
const children = [];
users.forEach((user) => {
    children = [...children, user.children];
});

// good
const children = users.reduce((currentChildren, user) => {
    return [...currentChildren, ...user.children];
}, []);

将数组数据传换成对象数据

// not good
const propsMap = {};
props.forEach((prop) => {
    map[prop.name] = prop.value;
});

// good
const propsMap = props.reduce((currentMap, prop) => {
    return {
        ...currentMap,
        [prop.name]: prop.value,
    };
});

将对象数据转换成数组

// not good
const propsArray = [];
for (let key in propsMap) {
    propsArray.push({ [key]: propsMap[key] });
}

// good
const propsArray = Object.keys(propsMap).map((key) => {
    return { [key]: propsMap[key] };
});

有条件地赋值变量

// not good
let imageURL = 'default-state';
if (state === 0) {
    imageURL = 'disabled-state';
}
img.src = imageURL;

// good
const getImageURL = (state) => {
    if (state === 0) {
        return 'disabled-state';
    }
    return 'default-state';
};
const imageURL = getImageURL(state);
img.src = imageURL;

删除数组中的几项

应该考虑成生成一个新的数组,其中的数据是原来的数组的一部分。参考上面的 filter 用法。

向数组中添加几项

// not good
users.push(...newUsers);

// good
const finalUsers = [...users, ...newUsers];

删除对象中的一个值

// not good
delete user.name;

// not good
Reflect.deleteProperty(user, 'name');

// good
const { name: $_1, ...userWithoutName } = user; // 把 `user` 变量解构,除了 `name` 之外的属性都赋值给 `userWithoutName` 变量

生成长度为 N 的数组

Array.from({ length: N }, (item, index) => {
    return index;
});