如何在一个对象中初始化对象和对象数组并在每个对象中运行相同的功能?

时间:2019-06-25 23:07:33

标签: javascript

我具有以下数据结构:

const test1 = {
  hero: {
    update() {
      console.log('updated hero in object');
    },
  },
  zombies: [
    {
      update() {
        console.log('updated zombie 1 in array of objects');
      },
    },
    {
      update() {
        console.log('updated zombie 2 in array of objects');
      },
    },
  ],
};

我可以通过以下方式手动运行功能:

test1.hero.update()
test1.zombies[0].update()
test1.zombies[1].update()

但是会有数百个僵尸,其他数组和单个对象。

我是否需要递归才能全部运行它们,或者可以使用filterreduce?我有以下代码片段,但似乎无法使其运行这些功能。 KEY是update,而VALUE是update()的事实使我不知所措!

我之前做了作弊,只是将hero本身放在一个数组中,然后使用Object.keys和2个嵌套的forEach很容易,但这似乎是一个很弱的解决方案

// Code shows keys and values of everything, but cant't run update()
const iterate = obj => {
  Object.keys(obj).forEach(key => {
    console.log(`KEY: ${key}, VALUE: ${obj[key]}`);
    if (typeof obj[key] === 'object') {
      iterate(obj[key]);
    }
  });
};

iterate(test1);

2 个答案:

答案 0 :(得分:2)

您可以使用Array.prototype.flatMap来实现。这是一个示例:

const test1 = {
  hero: {
    update() {
      console.log('updated hero in object');
    },
  },
  zombies: [
    {
      update() {
        console.log('updated zombie 1 in array of objects');
      },
    },
    {
      update() {
        console.log('updated zombie 2 in array of objects');
      },
    },
  ],
};

Array.prototype.flatMap = function (lambda) {
  return Array.prototype.concat.apply([], this.map(lambda));
};

const caller = (data) => {
  Object.entries(data)
    .flatMap((keyValueArray) => {
      const [key, objOrArrayValue] = keyValueArray;
      if (objOrArrayValue instanceof Array) {
        return objOrArrayValue;
      }
      return [objOrArrayValue];
    })
    .forEach(obj => obj.update());
};

caller(test1);

PS:为了演示,我从here获得了flatMap的实现

答案 1 :(得分:1)

这可以通过updateEntityArray()函数(见下文)实现,该函数提供了一种通用的递归解决方案:

const test1 = {
  hero: {
    update() {
      console.log('updated hero in object');
    },
  },
  zombies: [
    {
      update() {
        console.log('updated zombie 1 in array of objects');
      },
    },
    { 
      update() {
        console.log('updated zombie 2 in array of objects');
      },
    },
  ],
};

/* Generic function that recursively calls update() on items
in supplied entities */
const updateEntities = (entities) => {

  /* Iterate values of supplied entities */
  for(const entity of Object.values(entities)) {
  
    /* If this entity has an update function defined then call it */
    if(typeof entity.update === 'function') {
      entity.update();
    }
    
    /* If this entity is iterable then recursively call updateEntities
    where any updatable children of this entity will be up updated as
    well */
    if(typeof entity[Symbol.iterator] === 'function') {
      updateEntities(entity);
    }
  } 
}

updateEntities(test1);