如何在javascriptreduce函数中定义一个函数?

How to define a function in javascript reduce function?

我有一个学生对象,它有 属性 id、name、groupName。 allStudents 是学生对象的数组,我想把它变成一个 id 到 student 映射,但是对于每个学生,我想生成一个新的 属性 “label”,如果学生有 groupName,label 值为“ name + groupName”,否则就是name。所以我写了下面的代码,它有效:

const idsToStudents = allStudents.reduce((tempMap, student) => {
    const getStudentLabel = (student) => {
        if (student.groupName) {
            return [student.name, `(${student.groupName})`].join(' ');
        }
        return student.name;
    };
    const studentLabel = getStudentLabel(student);
    return {
        ...tempMap,
        [student.id]: { ...student, label: studentLabel}
    };
}, {});

我在 reducer 函数中定义了 getStudentLabel 函数,有没有更好的方法来代替在 reducer 函数中一次又一次地声明 getStudentLabel 函数?你可以忽略 getStudentLabel 到底做了什么,只是认为它把每个人作为参数和 return 一些基于人的东西,有没有办法只定义一次函数,但我仍然可以为 reducer 中的每个人调用它?

谢谢!

您将 student 作为参数传递给函数,因此您不需要在 reduce 中声明它。这也行得通:

const getStudentLabel = (student) => {
  if (student.groupName) {
    return [student.name, `(${student.groupName})`].join(' ');
  }
  
  return student.name;
};

const idsToStudents = allStudents.reduce((tempMap, student) => {
  const studentLabel = getStudentLabel(student);
  return {
      ...tempMap,
      [student.id]: { ...student, label: studentLabel}
  };
}, {});

您还可以缩短代码:

const getStudentLabel = ({ name, groupName }) => groupName
  ? `${name} (${groupName})`
  : name;

const idsToStudents = allStudents.reduce((tempMap, student) => ({
  ...tempMap,
  [student.id]: { ...student, label: getStudentLabel(student) }
}), {});

我不担心在闭包内重新定义函数。任何合理的 javascript 实现都会对其进行优化,以便使用最少的额外内存。我不会说您不止一次“定义”该函数是准确的-您只在代码中定义了一次。函数每次都被实例化,但是这个实例化将利用函数静态部分的缓存。所以你这样做的方式非常好。正如 Ori Drori 提到的那样,您不必 必须 在内部函数中使用 student 变量,但无论如何这样做可能是个好主意,这样您就可以非常明确地了解函数的依赖项。

Object.fromEntries 可以替代 reduce.

const getStudentLabel = ({name, groupName}) => groupName
  ? name + ` (${groupName})`
  : name;

const idsToStudents = Object.fromEntries(
  allStudents.map(student => [student.id, { ...student, label: getStudentLabel(student) }])
);