如何在递归函数中维护变量?

Dan*_*mes 3 javascript recursion

我试图以递归方式获取对象中的所有键:

let keys = [];

const getAllKeys = (object) => {
  //Supposedly, `keys` should be here.
  Object.keys(object).some((k) => {
    if (object[k] && typeof object[k] === "object") {
      keys.push(k);
      getAllKeys(object[k]);
    }
  });
  return keys;
};

const obj = {
  key1: {
    key2: {
      key3: {}
    }
  }
};

getAllKeys(obj);

console.log(keys);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它可以工作,但问题是它keys在这个函数之外,但我需要它在里面,这样我就可以只使用import这个函数并使用它。我尝试将其包装在另一个内部函数中,但它不起作用。

我在这里能做什么?

geo*_*org 5

您需要一个包装函数来保存累加器:

const getAllKeys = (object) => {
    let keys = [];

    let getAllKeysInner = (o) => {
        Object.keys(o).forEach((k) => {
            keys.push(k);
            if (o[k] && typeof o[k] === "object") {
                getAllKeysInner(o[k]);
            }
        });
    }

    getAllKeysInner(object)
    return keys;
};

//

const obj = {
    key1: {
        key2: {
            key3: {}
        }
    }
};

console.log(getAllKeys(obj))
Run Code Online (Sandbox Code Playgroud)

请注意,您的代码需要进行一些修复。

FWIW,这个特殊问题可以更简单地完成,根本不需要任何累加器:

const getAllKeys = (o) =>
    (o && typeof o === "object")
        ? Object.keys(o).flatMap(k => [k, ...getAllKeys(o[k])])
        : []
Run Code Online (Sandbox Code Playgroud)

尽管累加器版本可能更有效,因为它不分配 1000 个临时数组。

最后,VLAZ 携带累加器的想法是明智的,因为它与包装器版本一样高效。可以简洁地写成这样:

const getAllKeys = (o, keys=[]) =>
    o
    && typeof o === "object"
    && Object.keys(o).forEach(k => keys.push(k) && getAllKeys(o[k], keys))
    || keys
Run Code Online (Sandbox Code Playgroud)