javascript - 嵌套 JSON 迭代,超出最大调用堆栈大小

标签 javascript json recursion underscore.js jqxtreegrid

我已经实现了一个递归函数来迭代嵌套的 JSON。我面临的问题是它抛出错误

Maximum call stack exceeded

我实现的功能如下,

function createTreeMap (treeCatalog){
  var _this = this;

  _.each(treeCatalog, function (ele, inx){
    if(typeof (ele) === "object"){
      createTreeMap(ele);
    }else{
      //I create another JSON structure with the value as its property and its value as 1.
      _this.treeMap[ele] = 1;

    }
  });

}

我正在迭代的 JSON 看起来像这样,

[{
    "EmployeeID": 2,
    "FirstName": "Andrew",
    "LastName": "Fuller",
    "Country": "USA",
    "Title": "Vice President, Sales",
    "HireDate": "1992-08-14 00:00:00",
    "BirthDate": "1952-02-19 00:00:00",
    "City": "Tacoma",
    "Address": "908 W. Capital Way",
    children: [{
        "EmployeeID": 8,
        "FirstName": "Laura",
        "LastName": "Callahan",
        "Country": "USA",
        "Title": "Inside Sales Coordinator",
        "HireDate": "1994-03-05 00:00:00",
        "BirthDate": "1958-01-09 00:00:00",
        "City": "Seattle",
        "Address": "4726 - 11th Ave. N.E."
    }, {
        "EmployeeID": 1,
        "FirstName": "Nancy",
        "LastName": "Davolio",
        "Country": "USA",
        "Title": "Sales Representative",
        "HireDate": "1992-05-01 00:00:00",
        "BirthDate": "1948-12-08 00:00:00",
        "City": "Seattle",
        "Address": "507 - 20th Ave. E.Apt. 2A"
    }, {
        "EmployeeID": 3,
        "FirstName": "Janet",
        "LastName": "Leverling",
        "Country": "USA",
        "Title": "Sales Representative",
        "HireDate": "1992-04-01 00:00:00",
        "BirthDate": "1963-08-30 00:00:00",
        "City": "Kirkland",
        "Address": "722 Moss Bay Blvd."
    }, {
        "EmployeeID": 4,
        "FirstName": "Margaret",
        "LastName": "Peacock",
        "Country": "USA",
        "Title": "Sales Representative",
        "HireDate": "1993-05-03 00:00:00",
        "BirthDate": "1937-09-19 00:00:00",
        "City": "Redmond",
        "Address": "4110 Old Redmond Rd."
    }, {
        "EmployeeID": 5,
        "FirstName": "Steven",
        "LastName": "Buchanan",
        "Country": "UK",
        "Title": "Sales Manager",
        "HireDate": "1993-10-17 00:00:00",
        "BirthDate": "1955-03-04 00:00:00",
        "City": "London",
        "Address": "14 Garrett Hill",
        "expanded": "true",
        children: [{
            "EmployeeID": 6,
            "FirstName": "Michael",
            "LastName": "Suyama",
            "Country": "UK",
            "Title": "Sales Representative",
            "HireDate": "1993-10-17 00:00:00",
            "BirthDate": "1963-07-02 00:00:00",
            "City": "London",
            "Address": "Coventry House Miner Rd."
        }, {
            "EmployeeID": 7,
            "FirstName": "Robert",
            "LastName": "King",
            "Country": "UK",
            "Title": "Sales Representative",
            "HireDate": "1994-01-02 00:00:00",
            "BirthDate": "1960-05-29 00:00:00",
            "City": "London",
            "Address": "Edgeham Hollow Winchester Way"
        },{
            "EmployeeID": 9,
            "FirstName": "Anne",
            "LastName": "Dodsworth",
            "Country": "UK",
            "Title": "Sales Representative",
            "HireDate": "1994-11-15 00:00:00",
            "BirthDate": "1966-01-27 00:00:00",
            "City": "London",
            "Address": "7 Houndstooth Rd."
        }]
    }]
}];

我怀疑是相似的子属性名称。但是是否有适当的方法来解决这个问题,因为相似的子名称是必需的。

非常感谢:)

更新

此示例模拟了我遇到的问题:http://jsfiddle.net/qaoapays/1/

最佳答案

将源绑定(bind)到 jqxTreeGrid 后,对其结构进行一些小更改:添加 parent 属性和 data 属性,其中 data - 对 self 的引用。
作为解决方法,为了避免无限递归,您需要错过此属性,例如

function iterate (obj){
    _.each(obj, function(ele, inx){
        if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
            iterate(ele);
        }else{
            console.log(ele);
        }
    });
}

  var employees = 
      [{
      "EmployeeID": 2,
          "FirstName": "Andrew",
          "LastName": "Fuller",
          "Country": "USA",
          "Title": "Vice President, Sales",
          "HireDate": "1992-08-14 00:00:00",
          "BirthDate": "1952-02-19 00:00:00",
          "City": "Tacoma",
          "Address": "908 W. Capital Way",
     children: [{
          "EmployeeID": 8,
              "FirstName": "Laura",
              "LastName": "Callahan",
              "Country": "USA",
              "Title": "Inside Sales Coordinator",
              "HireDate": "1994-03-05 00:00:00",
              "BirthDate": "1958-01-09 00:00:00",
              "City": "Seattle",
              "Address": "4726 - 11th Ave. N.E."
      }, {
          "EmployeeID": 1,
              "FirstName": "Nancy",
              "LastName": "Davolio",
              "Country": "USA",
              "Title": "Sales Representative",
              "HireDate": "1992-05-01 00:00:00",
              "BirthDate": "1948-12-08 00:00:00",
              "City": "Seattle",
              "Address": "507 - 20th Ave. E.Apt. 2A"
      }, {
          "EmployeeID": 3,
              "FirstName": "Janet",
              "LastName": "Leverling",
              "Country": "USA",
              "Title": "Sales Representative",
              "HireDate": "1992-04-01 00:00:00",
              "BirthDate": "1963-08-30 00:00:00",
              "City": "Kirkland",
              "Address": "722 Moss Bay Blvd."
      }, {
          "EmployeeID": 4,
              "FirstName": "Margaret",
              "LastName": "Peacock",
              "Country": "USA",
              "Title": "Sales Representative",
              "HireDate": "1993-05-03 00:00:00",
              "BirthDate": "1937-09-19 00:00:00",
              "City": "Redmond",
              "Address": "4110 Old Redmond Rd."
      }, {
          "EmployeeID": 5,
              "FirstName": "Steven",
              "LastName": "Buchanan",
              "Country": "UK",
              "Title": "Sales Manager",
              "HireDate": "1993-10-17 00:00:00",
              "BirthDate": "1955-03-04 00:00:00",
              "City": "London",
              "Address": "14 Garrett Hill",
              "expanded": "true",
          children: [{
              "EmployeeID": 6,
                  "FirstName": "Michael",
                  "LastName": "Suyama",
                  "Country": "UK",
                  "Title": "Sales Representative",
                  "HireDate": "1993-10-17 00:00:00",
                  "BirthDate": "1963-07-02 00:00:00",
                  "City": "London",
                  "Address": "Coventry House Miner Rd."
          }, {
              "EmployeeID": 7,
                  "FirstName": "Robert",
                  "LastName": "King",
                  "Country": "UK",
                  "Title": "Sales Representative",
                  "HireDate": "1994-01-02 00:00:00",
                  "BirthDate": "1960-05-29 00:00:00",
                  "City": "London",
                  "Address": "Edgeham Hollow Winchester Way"
          }, {
              "EmployeeID": 9,
                  "FirstName": "Anne",
                  "LastName": "Dodsworth",
                  "Country": "UK",
                  "Title": "Sales Representative",
                  "HireDate": "1994-11-15 00:00:00",
                  "BirthDate": "1966-01-27 00:00:00",
                  "City": "London",
                  "Address": "7 Houndstooth Rd."
          }]
      }]
  }];

  //// prepare the data
  var source = {
      dataType: "json",
      dataFields: [{
          name: 'EmployeeID',
          type: 'number'
      }, {
          name: 'FirstName',
          type: 'string'
      }, {
          name: 'LastName',
          type: 'string'
      }, {
          name: 'Country',
          type: 'string'
      }, {
          name: 'City',
          type: 'string'
      }, {
          name: 'Address',
          type: 'string'
      }, {
          name: 'Title',
          type: 'string'
      }, {
          name: 'HireDate',
          type: 'date'
      }, {
          name: 'children',
          type: 'array'
      }, {
          name: 'expanded',
          type: 'bool'
      }, {
          name: 'BirthDate',
          type: 'date'
      }],
      hierarchy: {
          root: 'children'
      },
      id: 'EmployeeID',
      localData: employees
  };
  var dataAdapter = new $.jqx.dataAdapter(source);

  // create Tree Grid
  $("#treeGrid").jqxTreeGrid({
      width: 680,
      source: dataAdapter,
      editable: true,
      filterable: true,
      theme: 'energyblue',
      columns: [{
          text: 'FirstName',
          dataField: 'FirstName',
          width: 150
      }, {
          text: 'LastName',
          dataField: 'LastName',
          width: 120
      }, {
          text: 'Title',
          dataField: 'Title',
          width: 200
      }, {
          text: 'Birth Date',
          dataField: 'BirthDate',
          cellsFormat: 'd',
          width: 120
      }, {
          text: 'Hire Date',
          dataField: 'HireDate',
          cellsFormat: 'd',
          width: 120
      }, {
          text: 'Address',
          dataField: 'Address',
          width: 250
      }, {
          text: 'City',
          dataField: 'City',
          width: 120
      }, {
          text: 'Country',
          dataField: 'Country',
          width: 120
      }]

  });
  $("#jqxbutton").jqxButton({
      theme: 'energyblue',
      height: 30
  });
  $('#jqxbutton').click(function () {
      $("#treeGrid").jqxTreeGrid('expandRow',2);
      iterate(employees);
      });

  function iterate (obj){
    _.each(obj, function(ele, inx){
          if(typeof (ele) === "object" && ele !== obj && inx !== 'parent'){
              iterate(ele);
          }else{
              console.log(ele);
          }
      });
  }
<script src="http://documentcloud.github.io/underscore/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.energyblue.css" rel="stylesheet"/>
<link href="http://jqwidgets.com/public/jqwidgets/styles/jqx.base.css" rel="stylesheet"/>
<script src="http://jqwidgets.com/public/jqwidgets/jqx-all.js"></script>
<div id="treeGrid"></div>
<input type="button" style="margin: 20px;" id="jqxbutton" value="Expand a row" />

另一种方式:传递给源 - 深度克隆对象

关于javascript - 嵌套 JSON 迭代,超出最大调用堆栈大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30372576/

相关文章:

javascript - Phonegap - 如何从 base64 字符串生成图像文件?

javascript - 支持 'Quick Sort' 算法

recursion - Django CMS 多级下拉菜单

javascript - 如何从运行 PHP 和 MySQL 的 Web 服务器读取 JSON 数据?

javascript - 将 Canvas 元素放在前面?

c# - 在json中插入c#数组

javascript - 如何使用 json 从 php 将响应返回到 javascript?

c - 在递归函数中使用结构(引用结构)

javascript - 如何从 firestore 中的数组中删除对象

javascript - 如何在 JavaScript 中使用 $.getJSON 检索 python 文件数据?