在Javascript中从嵌套对象/数组中提取键和值

在Javascript中从嵌套对象/数组中提取键和值,javascript,typescript,algorithm,Javascript,Typescript,Algorithm,我正在使用动态表单生成器,其中行/列网格结构中有表单元素,我的每个表单元素(对象)都有一个名为model的特殊键,该键定义字段名,值键定义其值。我有一个嵌套的表单,它也有同样的功能,我需要提取这些模型和值,并使它们成为一个对象,在FormRepeater的情况下,它将是一个数组。以下是我的表单数据的示例格式: [ { "component":"row", "attrs":{ "c

我正在使用动态表单生成器,其中行/列网格结构中有表单元素,我的每个表单元素(对象)都有一个名为model的特殊键,该键定义字段名,值键定义其值。我有一个嵌套的表单,它也有同样的功能,我需要提取这些模型和值,并使它们成为一个对象,在FormRepeater的情况下,它将是一个数组。以下是我的表单数据的示例格式:

[
   {
      "component":"row",
      "attrs":{
         "child_components":[
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"first_name",
                           "value":"",
                        }
                     },
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"last_name",
                           "value":"",
                        }
                     }
                  ]
               }
            },
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"form-repeater",
                        "attrs":{
                           "child_components":[
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value": ""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              },
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value":""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              }
                           ],
                           "model":"links",
                           "value":""
                        }
                     }
                  ]
               }
            }
         ]
      }
   }
]
要执行此操作,我尝试创建一个递归函数:

findModel(ele) {
  ele.forEach((element) => {
    if(typeof element.attrs.model !== 'undefined') {
      if(element.component === 'form-repeater') {
        let repeater = [];
        element.attrs.child_components.forEach((rep) => {
          let data = this.findModel(rep.attrs.child_components);
          repeater.push(data);
        })
        const repeaterData = {}
        repeaterData[element.attrs.model] = repeater;
        return repeaterData;
      }
      else {
        const data = {}
        data[element.attrs.model] = element.attrs.value;
        return data;
      }
    }
    else {
      if(typeof element.attrs.child_components !== 'undefined' && element.attrs.child_components.length) {
        return this.findModel(element.attrs.child_components);
      }
    }
  })
},
let data = findModel(form_data)
console.log(data)
//Always comes undefined.
我调用这个函数:

findModel(ele) {
  ele.forEach((element) => {
    if(typeof element.attrs.model !== 'undefined') {
      if(element.component === 'form-repeater') {
        let repeater = [];
        element.attrs.child_components.forEach((rep) => {
          let data = this.findModel(rep.attrs.child_components);
          repeater.push(data);
        })
        const repeaterData = {}
        repeaterData[element.attrs.model] = repeater;
        return repeaterData;
      }
      else {
        const data = {}
        data[element.attrs.model] = element.attrs.value;
        return data;
      }
    }
    else {
      if(typeof element.attrs.child_components !== 'undefined' && element.attrs.child_components.length) {
        return this.findModel(element.attrs.child_components);
      }
    }
  })
},
let data = findModel(form_data)
console.log(data)
//Always comes undefined.
我的最终数据格式将是这样的,这是我无法实现的:

{
    first_name: '',
    last_name: '',
    links: [
        {name: '', url: ''},
        {name: '', url: ''}
    ]
}

帮助我实现上述格式。任何更好的方法都是最受欢迎的。谢谢。

您的函数返回
未定义的
,因为它没有
返回
语句。您拥有的
return
语句是从
forEach
回调返回的,这显然不是同一个函数

forEach
回调中返回一个值是无用的,因为该值会消失在遗忘中。forEach的
forEach
不适用于此

您需要:

  • 使用
    .map
    而不是
    .forEach
  • 返回
    .map
  • 因此:

    最后,在回调逻辑中有一个不返回值的情况:外部
    else
    块在
    if
    块中有一个
    return
    ,但是当内部
    if
    条件为非真时,没有
    return
    语句。因此,从理论上讲,回调在某些情况下可能返回未定义的,这意味着
    .map
    将返回一个包含潜在未定义元素的数组


    您应该确保回调代码中的所有情况都会导致受控的
    返回

    递归是正确的方法。代码可能会更干净一些,但也不坏你的问题是什么?如果您正在寻找代码审查和改进建议,那么您可能希望@mbdavis我的代码不起作用。需要获得所需格式的帮助。@AluanHaddad您能帮我吗?@AluanHaddad递归函数不起作用,它总是抛出
    未定义的数据集。如果你搞错了,我的错。