首页 > 解决方案 > 使用带有 Javascript 对象的纯函数

问题描述

假设我有这样的代码:

function example() {
  const obj = {};
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j< 10; j++) {
       if (obj[i] == undefined) {
         obj[i] = 0;
       }
       if (obj[j] == undefined) {
         obj[j] = 0;
       } else {
         obj[i] += i;
         obj[j] += j;
       }
    }
  }
}

在这里你可以看到:

if (obj[i] == undefined) {
  obj[i] = 0;
}

我检查是否i不在obj我用 0 分配i里面的键obj,否则我什么都不做,我用j.

代码是重复的,我不想重复自己,这是不好的做法,所以我创建了另一个函数来申请ij就像这样:

function initObjWithValue(obj, keys) {
  for (const key of keys) {
    if (obj[key] === undefined) {
      obj[key] = 0;
    }
  }
}

这个功能很容易理解吧?它的第一个参数是对象,第二个参数是要检查的键数组。现在我可以像这样重构我的代码:

function example() {
  const obj = {};
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j< 10; j++) {
       initObjWithValue(obj, [i, j]);
       obj[i] += i;
       obj[j] += j;
    }
  }
}

代码更清晰,但正如您在我的函数中看到的那样initObjWithValue,它发生了变异obj,我认为它不好。以下是维基页面的引用:

在计算机编程中,纯函数是具有以下属性的函数: 对于相同的参数,它的返回值相同(与局部静态变量、非局部变量、可变引用参数或来自 I/O 设备的输入流没有变化) )。

而我被卡在了这一点上,我怎么能不重复自己,在这种情况下我可以实现纯功能?

标签: javascriptpurely-functional

解决方案


您可以改为initObjectWithValue返回一个新对象,然后您可以将其与当前的obj. 这样,您所做的就是从 中读取obj,而不是在 中对其进行变异initObjectWithValue

function initObjWithValue(obj, keys) {
  const tmp = {};
  for (const key of keys) {
    if (!(key in obj)) {
      tmp[key] = 0;
    }
  }
  return tmp;
}

function example() {
  const obj = {};
  for (let i = 0; i < 10; i++) {
    for (let j = 0; j< 10; j++) {
       Object.assign(obj, initObjWithValue(obj, [i, j])); // merge the return with current object
       obj[i] += i;
       obj[j] += j;
    }
  }
  return obj;
}

console.log(example());


推荐阅读