2

I have a general function that I want to call with any object structure. Some of the objects has arrays of objects which then again have arrays of objects etc.

The only way I got it to work was like this and it does not seem like the most clever way of doing it cause I keep adding depth to the function.

Is there a better way? I tried a recursive function I found here on stack, but couldn't get it to work.

// Look for everyting at level ONE
for (var property in textfield) {
  // Is there a field?
  if (textfield.hasOwnProperty(property)) {
    // Is level ONE an OBJECT
    if (typeof textfield[property] == "object") {
      // Look for everyting at level TWO
      for (var subProperty in textfield[property]) {
        // Is there a field?
        if (textfield[property].hasOwnProperty(subProperty)) {
          // Is level TWO an OBJECT
          if (typeof textfield[property][subProperty] == "object") {
            // Look for everyting at level THREE
            for (var subSubProperty in textfield[property][subProperty]) {
              // Is there a field?
              if (textfield[property][subProperty].hasOwnProperty(subSubProperty)) {
                // Is level THREE an OBJECT
                if (typeof textfield[property][subProperty][subSubProperty] == "object") {
                  // Look for everyting at level FOUR
                  for (var subSubSubProperty in textfield[property][subProperty][subSubProperty]) {
                    // Translate everything at level FOUR
                    console.log("-----------------------LEVEL 4")
                    console.log("LOOP: " + textfield[property][subProperty][subSubProperty][subSubSubProperty]);
                    console.log("TYPE: " + typeof textfield[property][subProperty][subSubProperty][subSubSubProperty]);
                    textfield[property][subProperty][subSubProperty][subSubSubProperty] = replaceFields(textfield[property][subProperty][subSubProperty][subSubSubProperty]);
                  }
                } else {
                  // Translate everything at level THREE
                  console.log("-----------------------LEVEL 3")
                  console.log("LOOP: " + textfield[property][subProperty][subSubProperty]);
                  console.log("TYPE: " + typeof textfield[property][subProperty][subSubProperty]);
                  textfield[property][subProperty][subSubProperty] = replaceFields(textfield[property][subProperty][subSubProperty]);
                }
              }
            }
          } else {
            // Translate everything at level TWO
            console.log("-----------------------LEVEL 2")
            console.log("LOOP: " + textfield[property][subProperty]);
            console.log("TYPE: " + typeof textfield[property][subProperty]);
            textfield[property][subProperty] = replaceFields(textfield[property][subProperty]);
          }
        }
      }
    } else {
      // Translate everything at level ONE
      console.log("-----------------------LEVEL 1")
      console.log("LOOP: " + textfield[property]);
      console.log("TYPE: " + typeof textfield[property]);
      textfield[property] = replaceFields(textfield[property]);
    }
  }
}

Thanks to Jinweizhu's answer below, this is the final version and it works perfectly!!

function translateAll(textfield) {
    for (var property in textfield) {
        if (!textfield.hasOwnProperty(property)) {
            return false;
        } else if (typeof textfield[property] !== "object") {
            textfield[property] = replaceFields(textfield[property]);
        } else {
            translateAll(textfield[property]);
        }
    }
}
torbenrudgaard
  • 2,375
  • 7
  • 32
  • 53

2 Answers2

2

I'm not sure what do you want to do with your objects or arrays values but I hope this will help you. The following function prints the values and calls itself recursively in case of objects or arrays:

const getValues = (value, path = '') => {  
  if (typeof value === 'object'
    && value !== null
    && value.length === undefined
    && Object.keys(value).length > 0) {
    // It is an Object (not null, array or Date instance)
    Object.keys(value).forEach((prop) => {
      const _path = path.length ? `${path}.${prop}` : prop;
      getValues(value[prop], _path);
    });
  } else if (typeof value === 'object'
    && value !== null
    && value.length  > 0) {
    // It is an array
    value.forEach((item, idx) => {
      const _path = path.length ? `${path}[${idx}]` : idx;
      getValues(item, _path);
    });
  } else {
    console.log(`${path} = ${JSON.stringify(value)}`);
  }
};

For example:

const obj = {
  a: 1,
  b: { a: 1, b: 2 },
  c: [
    { a: 1, b: 2 },
    { a: 1, b: 2 },
  ],
  d: {},
  e: [],
  f: new Date(),
  g: null,
  h: undefined,
};
getValues(obj, 'obj');

Will output:

obj.a = 1
obj.b.a = 1
obj.b.b = 2
obj.c[0].a = 1
obj.c[0].b = 2
obj.c[1].a = 1
obj.c[1].b = 2
obj.d = {}
obj.e = []
obj.f = "2020-07-14T06:02:12.037Z"
obj.g = null
obj.h = undefined
virgiliogm
  • 946
  • 7
  • 15
2

I'm not sure what you mean is the same as what I understand.

let index = 0;
function fn(textfield) {
    index++;
    for (var property in textfield) {
        if (!textfield.hasOwnProperty(property)) {
            return false;
        } else if (typeof textfield[property] !== "object") {
            console.log("-----------------------LEVEL " + index);
            console.log("LOOP: " + textfield[property]);
            console.log("TYPE: " + typeof textfield[property]);
            // textfield[property] = replaceFields(textfield[property]);
        } else {
            fn(textfield[property]);
        }
    }
}
const obj = {a:{ b: { c: { d:1} } }};
fn(obj);
iopzhu
  • 149
  • 5