前言:设计通用性函数,我们需要考虑两个方面,一个是函数传参的可能性,如果可能性很多,我们可以将处理参数的方法暴露出去,让使用者去设计。为了调用的方便性,我们还可以做参数的归一化。
举个例子:有一个 people 数组如下,现在需要开发者给这个数组按 sex 分组。man 的一组,woman 的一组。
const people = [
{ name: "a", age: 1, sex: "man" },
{ name: "b", age: 2, sex: "woman" },
{ name: "c", age: 3, sex: "man" },
{ name: "d", age: 4, sex: "man" },
{ name: "e", age: 1, sex: "woman" },
{ name: "f", age: 1, sex: "man" },
{ name: "g", age: 1, sex: "man" },
{ name: "h", age: 2, sex: "woman" },
];
1. 普通函数的封装
构建一个函数,传入两个参数,数组和决定分组的 key。
这样看着还挺好,但是有个问题,就是这个函数的局限性。我们只能确定我们第一个传入的是数组,但是我们不能确定数组里面的项是什么,这个函数就固定了传入的数组必须是对象数组,且第二个参数,必须是对象里的属性,这个函数才能生效。
const groupBy = (arr, key) => {
let result = {};
arr.forEach((item) => {
const _key = item[key];
if (result[_key]) {
result[_key].push(item);
} else {
result[_key] = [item];
}
});
return result;
};
2. 公共函数的封装
构建一个函数,功能和上面那个一样。
但是这个函数将第二个参数暴露给了开发人员,开发人员需要按照什么形式分组,都可以自己定义,而且我们也做了参数的归一化,如果第二个参数没有传回调函数,而是传的字符串,我们可以将这个字符串,在函数的内部转换成回调函数。就相当于开发者还是传入的回调函数。
const groupBy = (arr, callback) => {
if (typeof callback === "string") {
const keyName = callback;
callback = (item) => item[keyName];
}
let result = {};
arr.forEach((item, index) => {
const _key = callback(item, index, arr);
if (result[_key]) {
result[_key].push(item);
} else {
result[_key] = [item];
}
});
return result;
};
用公共函数,我们实现按 "性别-年龄" 的形式完成分组
groupBy(people, (item) => `${item.sex}-${item.age}`);