Traverse and modify a deep object I wrote this piece of code yesterday at work. This function will traverse a deep nested object to find and modify a value.

I know it's bad, so I am trying to refactor it. I have not found any significant way to improve it. This is kind of dealing with legacy code. Changing the object structure is off the book, I should only modify this function, because things are working I don't dare to touch other parts.

How would you refactor this?

Object structure:

{
    panel1Name: {
        screen: {
            screen1Name: {
                variable: {
                    var1: {
                        custom: [],
                    },
                    var2: {
                        custom: [],
                    },
                    var3: {
                        custom: [],
                    },
                    // many other var
                }
            },
            screen2Name: {
                // ...
            },
            // many other screens
        }
    },
    panel2Name: {
        // ...
    },
    // many other panels
}

// custom is the value I need to check and modify




Code

function removeImageFromSettings(imageName) {
  for (let panel in $scope.data) {
    if ($scope.data.hasOwnProperty(panel)) {
      for (let screen in $scope.data[panel].screen) {
        if ($scope.data[panel].screen.hasOwnProperty(screen)) {
          for (let variable in $scope.data[panel].screen[screen].variable) {
            if ($scope.data[panel].screen[screen].variable.hasOwnProperty(variable)) {
              const data = $scope.data[panel].screen[screen].variable[variable];

              if (data.custom &amp;&amp; data.custom[0] === imageName) {
                data.custom[0] = '';
              }
            }
          }
        }
      }
    }
  }
}
You could move the logic that gets each panel / screen etc into it's own function, and remove some of the indenting, like so:

function getChildren(obj) {
    // No need to check hasOwnProperty, and keys only returns ownProperties
    return obj ? Object.keys(obj).map(function(key) {return obj[key]}) : [];
}


function removeImageFromSettings(imageName) {
    let panels = getChildren($scope.data);

    let screens = panels.reduce(function(result, panel) {
        return result.concat(getChildren(panel.screen));
    }, []);

    let variables = screens.reduce(function(result, screen) {
        return result.concat(getChildren(screen.variable));
    }, []);

    variables.forEach(function(variable) {
        if (variable.custom &amp;&amp; variable.custom[0] === imageName) {
            variable.custom[0] = "";
        }
    });
}